[MIRROR] Fixing fish hook exploits, bait not being consumed, race conditions and achievement [MDB IGNORE] (#23690)

* Fixing fish hook exploits, bait not being consumed, race conditions and achievement (#78302)

## About The Pull Request
The bait wasn't being consumed properly because it was badly coded.
Whoopsies.
The achievement would be unlocked upon gaining legendary rank ONLY IF
you won the minigame. My bad.
Upon win (and loss), the fishing minigame would often be prematurely
closed before ui act could run due to internal calls to do that. A
classic example of race condition.
Last but not least, the fishing hook exploit that would allow items to
be in multiple places, including nullspace, and cause a load of issues.

## Why It's Good For The Game
This PR should fix all of them. Closes #78210, closes #78204, closes
#78187, closes #77265, closes #77265, closes #73014.

## Changelog

🆑
fix: Fixed a race condition that made fishing yield no reward way too
often.
fix: The legendary fisher achievement is awarded even if you don't win
the minigame.
fix: Fixed a fish hook exploit.
fix: Baits are now properly consumed by caught fish and (alive) mobs.
/🆑

* Fixing fish hook exploits, bait not being consumed, race conditions and achievement

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-09-14 23:37:49 -07:00
committed by GitHub
co-authored by Ghom
parent 5ce0f2fa1d
commit 47d1f9fc6d
3 changed files with 13 additions and 9 deletions
+4 -1
View File
@@ -86,6 +86,7 @@
QDEL_NULL(fishing_line)
if(lure)
QDEL_NULL(lure)
SStgui.close_uis(src)
user = null
used_rod = null
return ..()
@@ -148,6 +149,8 @@
complete(FALSE)
/datum/fishing_challenge/proc/complete(win = FALSE, perfect_win = FALSE)
if(completed)
return
deltimer(next_phase_timer)
completed = TRUE
if(user)
@@ -156,7 +159,7 @@
var/seconds_spent = (world.time - start_time) * 0.1
if(!(FISHING_MINIGAME_RULE_NO_EXP in special_effects))
user.mind?.adjust_experience(/datum/skill/fishing, round(seconds_spent * FISHING_SKILL_EXP_PER_SECOND * experience_multiplier))
if(win && user.mind?.get_skill_level(/datum/skill/fishing) >= SKILL_LEVEL_LEGENDARY)
if(user.mind?.get_skill_level(/datum/skill/fishing) >= SKILL_LEVEL_LEGENDARY)
user.client?.give_award(/datum/award/achievement/skill/legendary_fisher, user)
if(win)
if(reward_path != FISHING_DUD)
+8 -5
View File
@@ -118,11 +118,14 @@
return hook?.reason_we_cant_fish(target_fish_source)
/obj/item/fishing_rod/proc/consume_bait(atom/movable/reward)
if(!reward)
// catching things that aren't fish or alive mobs doesn't consume baits.
if(isnull(reward) || isnull(bait))
return
var/mob/living/caught_mob = isliving(reward) ? reward : null
// catching non-fish, non-mob movables, or dead mobs (probably from a chasm) doesn't consume baits.
if(!bait || !isfish(reward) || !caught_mob || (caught_mob && caught_mob.stat == DEAD))
if(isliving(reward))
var/mob/living/caught_mob = reward
if(caught_mob.stat == DEAD)
return
else if(!isfish(reward))
return
QDEL_NULL(bait)
update_icon()
@@ -208,7 +211,7 @@
SIGNAL_HANDLER
. = NONE
if(!CheckToolReach(src, source.target, cast_range))
if(!isturf(source.origin) || !isturf(source.target) || !CheckToolReach(src, source.target, cast_range))
SEND_SIGNAL(source, COMSIG_FISHING_LINE_SNAPPED) //Stepped out of range or los interrupted
return BEAM_CANCEL_DRAW
+1 -3
View File
@@ -4,7 +4,7 @@ import { randomInteger, randomNumber, randomPick, randomProb } from 'common/rand
import { useDispatch } from 'common/redux';
import { Component } from 'inferno';
import { resolveAsset } from '../assets';
import { backendSuspendStart, useBackend } from '../backend';
import { useBackend } from '../backend';
import { Icon, KeyListener } from '../components';
import { globalEvents, KeyEvent } from '../events';
import { Window } from '../layouts';
@@ -408,10 +408,8 @@ class FishingMinigame extends Component<
if (newCompletion <= 0 && !this.no_escape) {
this.props.lose();
dispatch(backendSuspendStart());
} else if (newCompletion >= 100) {
this.props.win();
dispatch(backendSuspendStart());
}
return newState;