Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing "COOLDOWN_LIST", and some botany changes #9324

Closed
wants to merge 12 commits into from
48 changes: 34 additions & 14 deletions code/__DEFINES/cooldowns.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@

//TIMER COOLDOWN MACROS

#define COMSIG_CD_STOP(cd_index) "cooldown_[cd_index]"
#define COMSIG_CD_RESET(cd_index) "cd_reset_[cd_index]"
#define COMSIG_CD_STOP(cd_name) "cooldown_[cd_name]"
#define COMSIG_CD_RESET(cd_name) "cd_reset_[cd_name]"

#define TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_index), cd_time))
#define TIMER_COOLDOWN_START(cd_source, cd_name, cd_time) LAZYSET(cd_source.cooldowns, cd_name, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_name), cd_time))

#define TIMER_COOLDOWN_CHECK(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index)
#define TIMER_COOLDOWN_CHECK(cd_source, cd_name) LAZYACCESS(cd_source.cooldowns, cd_name)

#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)
#define TIMER_COOLDOWN_END(cd_source, cd_name) LAZYREMOVE(cd_source.cooldowns, cd_name)

/*
* Stoppable timer cooldowns.
Expand All @@ -48,27 +48,47 @@
* A bit more expensive than the regular timers, but can be reset before they end and the time left can be checked.
*/

#define S_TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_index), cd_time, TIMER_STOPPABLE))
#define S_TIMER_COOLDOWN_START(cd_source, cd_name, cd_time) LAZYSET(cd_source.cooldowns, cd_name, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_name), cd_time, TIMER_STOPPABLE))

#define S_TIMER_COOLDOWN_RESET(cd_source, cd_index) reset_cooldown(cd_source, cd_index)
#define S_TIMER_COOLDOWN_RESET(cd_source, cd_name) reset_cooldown(cd_source, cd_name)

#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_index) (timeleft(TIMER_COOLDOWN_CHECK(cd_source, cd_index)))
#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_name) (timeleft(TIMER_COOLDOWN_CHECK(cd_source, cd_name)))


/*
* Cooldown system based on storing world.time on a variable, plus the cooldown time.
* Better performance over timer cooldowns, lower control. Same functionality.
*/

#define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0
#define COOLDOWN_DECLARE(cd_name) var/##cd_name = 0

#define COOLDOWN_STATIC_DECLARE(cd_index) var/static/##cd_index = 0
#define COOLDOWN_STATIC_DECLARE(cd_name) var/static/##cd_name = 0

#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + (cd_time))
#define COOLDOWN_START(cd_source, cd_name, cd_time) (cd_source.cd_name = world.time + (cd_time))

//Returns true if the cooldown has run its course, false otherwise
#define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time)
#define COOLDOWN_FINISHED(cd_source, cd_name) (cd_source.cd_name < world.time)

#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0
#define COOLDOWN_RESET(cd_source, cd_name) cd_source.cd_name = 0

#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
#define COOLDOWN_TIMELEFT(cd_source, cd_name) (max(0, cd_source.cd_name - world.time))



// when a timer should track targets individually
// this is useful when an item should individually trigger cooldown time per mob
#define COOLDOWN_LIST_DECLARE(cd_name) var/list/##cd_name = list()

#define COOLDOWN_STATIC_LIST_DECLARE(cd_name) var/static/list/##cd_name = list()

/// IMPORTANT: "cd_target_index" should be individual because it's assoc key
#define COOLDOWN_LIST_START(cd_source, cd_name, cd_target_index, cd_time) (cd_source.cd_name[cd_target_index] = world.time + (cd_time))

#define COOLDOWN_LIST_FINISHED(cd_source, cd_name, cd_target_index) (cd_source.cd_name[cd_target_index] < world.time)

#define COOLDOWN_LIST_RESET(cd_source, cd_name, cd_target_index) cd_source.cd_name[cd_target_index] = 0

#define COOLDOWN_LIST_TIMELEFT(cd_source, cd_name, cd_target_index) (max(0, cd_source.cd_name[cd_target_index] - world.time))

/// use to change existing cooldown
#define COOLDOWN_LIST_ADJUST_TIME(cd_source, cd_name, cd_target_index, cd_time) (cd_source.cd_name[cd_target_index] = cd_source.cd_name[cd_target_index] - (cd_time))
2 changes: 1 addition & 1 deletion code/modules/hydroponics/grown.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
/obj/item/reagent_containers/food/snacks/grown/proc/add_juice()
if(reagents)
if(bitesize_mod)
bitesize = 1 + round(reagents.total_volume / bitesize_mod)
bitesize = max(1, round(reagents.total_volume / bitesize_mod))
return 1
return 0

Expand Down
1 change: 1 addition & 0 deletions code/modules/hydroponics/grown/cannabis.dm
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,6 @@
desc = "You feel dizzy looking at it. What the fuck?"
icon_state = "ocannabis"
volume = 420
bitesize = 1
wine_power = 90
discovery_points = 300
24 changes: 22 additions & 2 deletions code/modules/hydroponics/plant_genes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -251,21 +251,28 @@
// Also affects plant batteries see capatative cell production datum
name = "Electrical Activity"
rate = 0.2
COOLDOWN_STATIC_LIST_DECLARE(recent_victims)

/datum/plant_gene/trait/cell_charge/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C)
if(!COOLDOWN_LIST_FINISHED(src, recent_victims, C)) // if you were a victim recently, you won't get it again
return
var/power = round(G.seed.potency*rate)
if(prob(power))
COOLDOWN_LIST_START(src, recent_victims, C, 2 SECONDS)
C.electrocute_act(power, G, 1, 1)
var/turf/T = get_turf(C)
if(C.ckey != G.fingerprintslast)
C.investigate_log("[C] has slipped on an electric plant at [AREACOORD(T)]. Last fingerprint: [G.fingerprintslast].", INVESTIGATE_BOTANY)
log_combat(C, G, "slipped on and got electrocuted by", null, "with the power of 10. Last fingerprint: [G.fingerprintslast]")

/datum/plant_gene/trait/cell_charge/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
if(!COOLDOWN_LIST_FINISHED(src, recent_victims, target)) // if you were a victim recently, you won't get it again
return
if(iscarbon(target))
var/mob/living/carbon/C = target
var/power = G.seed.potency*rate
if(prob(power))
COOLDOWN_LIST_START(src, recent_victims, C, 2 SECONDS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't make a lot of sense to have cooldowns on, they execute only on slip and squash which are discrete and non-repeatable events

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can happen when multiple items are thrown to a person, or when you step on a squashable slip plant. That's why CD check exists here

C.electrocute_act(round(power), G, 1, 1)
if(C.ckey != G.fingerprintslast)
log_combat(G.thrownby, C, "hit and electrocuted", G, "at [AREACOORD(G)] with power of [power]")
Expand Down Expand Up @@ -439,6 +446,7 @@

/datum/plant_gene/trait/stinging
name = "Hypodermic Prickles"
COOLDOWN_STATIC_LIST_DECLARE(recent_victims)

/datum/plant_gene/trait/stinging/on_slip(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
if(!isliving(target) || !G.reagents || !G.reagents.total_volume)
Expand All @@ -464,11 +472,23 @@
if(!L.reagents && !L.can_inject(null, 0))
return FALSE

var/injecting_amount = max(1, G.seed.potency*0.2) // Minimum of 1, max of 20
var/fraction = min(injecting_amount/G.reagents.total_volume, 1)
// Mechanism: It will always inject the amount as "injecting_amount" variable no matter the total size is
var/prick_efficiency = 0.02 // default (maximum: 2u)
if(locate(/datum/plant_gene/trait/squash) in G.seed.genes)
prick_efficiency = 0.01 // how can a smooth plant be deadly? (maximum: 1u)
else if(istype(G, /obj/item/seeds/nettle/death)) // as long as it has not Liquid Content
prick_efficiency = 0.06 // bonus to "death" nettle (maximum: 6u)
else if(G.force)
prick_efficiency = 0.04 // bonus to blunt plants (miaxmum: 4u)
if(!COOLDOWN_LIST_FINISHED(src, recent_victims, L)) // until 10s cooldown time from a victim is finished, the effective becomes half
prick_efficiency = round(prick_efficiency/2, 0.01) // i.e) 4u to 2u
Comment on lines +475 to +484
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A maximum of 2 units is just ridiculously low to the point where it isn't doing anything. The cooldown on this one doesn't make a lot of sense either since on throw/slip isn't highly repeated events like attacking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly it should be so. It's already horrible source of force-injection of toxins. 6u even does powerful enough.


var/injecting_amount = round(max(1, G.seed.potency * prick_efficiency), 0.1) // mimumum 1u to maximum 5/10/15/20u
var/fraction = min(injecting_amount/G.reagents.total_volume, 1) // Let's say you have 90u + 10u. Injecting 5u will be "4.5u + 0.5u" by the fraction
G.reagents.reaction(L, INJECT, fraction)
G.reagents.trans_to(L, injecting_amount)
to_chat(L, "<span class='danger'>You are pricked by [G]!</span>")
COOLDOWN_LIST_START(src, recent_victims, L, 10 SECONDS) // this refreshes 10s cooldown time. repeated attack will not be effective
return TRUE

/datum/plant_gene/trait/smoke
Expand Down
20 changes: 18 additions & 2 deletions code/modules/hydroponics/seeds.dm
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@
return initial(plant.name)
else
return "[initial(plant.name)] (renamed as [plantname])"

/obj/item/seeds/proc/log_rename(mob/user, obj/item, type, input)
src.investigate_log("[key_name(user)] has changed [type](of [src]) into '[input]'", INVESTIGATE_BOTANY)
EvilDragonfiend marked this conversation as resolved.
Show resolved Hide resolved
// log_game() might fit, but I wanted botany logs contained in a specific log file.
//---------

/// Setters procs ///
Expand Down Expand Up @@ -405,20 +409,32 @@
var/input = stripped_input(user,"What do you want to name the plant?", default=plantname, max_length=MAX_NAME_LEN)
if(QDELETED(src) || !user.canUseTopic(src, BE_CLOSE))
return
if(OOC_FILTER_CHECK(input))
EvilDragonfiend marked this conversation as resolved.
Show resolved Hide resolved
to_chat(src, "<span class='warning'>That message contained a word prohibited in OOC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ooc_chat'>\"[input]\"</span></span>")
return
log_rename(user, src, "plant name", input)
name = "pack of [input] seeds"
plantname = input
renamedByPlayer = TRUE

if(penchoice == "Plant Description")
var/input = stripped_input(user,"What do you want to change the description of the plant to?", default=plantdesc, max_length=MAX_NAME_LEN)
var/input = stripped_input(user,"What do you want to change the description of the plant to?", default=plantdesc, max_length=MAX_MESSAGE_LEN)
if(QDELETED(src) || !user.canUseTopic(src, BE_CLOSE))
return
if(OOC_FILTER_CHECK(input))
EvilDragonfiend marked this conversation as resolved.
Show resolved Hide resolved
to_chat(src, "<span class='warning'>That message contained a word prohibited in OOC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ooc_chat'>\"[input]\"</span></span>")
return
log_rename(user, src, "plant desc", input)
plantdesc = input

if(penchoice == "Seed Description")
var/input = stripped_input(user,"What do you want to change the description of the seeds to?", default=desc, max_length=MAX_NAME_LEN)
var/input = stripped_input(user,"What do you want to change the description of the seeds to?", default=desc, max_length=MAX_MESSAGE_LEN)
if(QDELETED(src) || !user.canUseTopic(src, BE_CLOSE))
return
if(OOC_FILTER_CHECK(input))
EvilDragonfiend marked this conversation as resolved.
Show resolved Hide resolved
to_chat(src, "<span class='warning'>That message contained a word prohibited in OOC chat! Consider reviewing the server rules.\n<span replaceRegex='show_filtered_ooc_chat'>\"[input]\"</span></span>")
return
log_rename(user, src, "seed desc", input)
desc = input
..() // Fallthrough to item/attackby() so that bags can pick seeds up

Expand Down