-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy path_clan.dm
261 lines (227 loc) · 11.3 KB
/
_clan.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/**
* Bloodsucker clans
*
* Handles everything related to clans.
* the entire idea of datumizing this came to me in a dream.
*/
/datum/bloodsucker_clan
///The bloodsucker datum that owns this clan. Use this over 'source', because while it's the same thing, this is more consistent (and used for deletion).
var/datum/antagonist/bloodsucker/bloodsuckerdatum
///The name of the clan we're in.
var/name = CLAN_NONE
///Description of what the clan is, given when joining and through your antag UI.
var/description = "The Caitiff is as basic as you can get with Bloodsuckers. \n\
Entirely Clan-less, they are blissfully unaware of who they really are. \n\
No additional abilities is gained, nothing is lost, if you want a plain Bloodsucker, this is it. \n\
The Favorite Vassal will gain the Brawn ability, to help in combat."
///The clan objective that is required to greentext.
var/datum/objective/clan_objective
///The icon of the radial icon to join this clan.
var/join_icon = 'icons/mob/bloodsucker_clan_icons.dmi'
///Same as join_icon, but the state
var/join_icon_state = "caitiff"
///Description shown when trying to join the clan.
var/join_description = "The default, Classic Bloodsucker."
///Whether the clan can be joined by players. FALSE for flavortext-only clans.
var/joinable_clan = TRUE
///How the Bloodsucker ranks up, if they do.
var/rank_up_type = BLOODSUCKER_RANK_UP_NORMAL
///Whether they become entirely stun immune when entering Frenzy.
var/frenzy_stun_immune = FALSE
///The clan's manipulation specialty.
var/control_type = BLOODSUCKER_CONTROL_BLOOD
///How we will drink blood using Feed.
var/blood_drink_type = BLOODSUCKER_DRINK_NORMAL
/datum/bloodsucker_clan/New(datum/antagonist/bloodsucker/owner_datum)
. = ..()
src.bloodsuckerdatum = owner_datum
RegisterSignal(bloodsuckerdatum, COMSIG_BLOODSUCKER_ON_LIFETICK, PROC_REF(handle_clan_life))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_RANK_UP, PROC_REF(on_spend_rank))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_PRE_MAKE_FAVORITE, PROC_REF(on_offer_favorite))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_MAKE_FAVORITE, PROC_REF(on_favorite_vassal))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_MADE_VASSAL, PROC_REF(on_vassal_made))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_EXIT_TORPOR, PROC_REF(on_exit_torpor))
RegisterSignal(bloodsuckerdatum, BLOODSUCKER_FINAL_DEATH, PROC_REF(on_final_death))
give_clan_objective()
/datum/bloodsucker_clan/Destroy(force)
UnregisterSignal(bloodsuckerdatum, list(
COMSIG_BLOODSUCKER_ON_LIFETICK,
BLOODSUCKER_RANK_UP,
BLOODSUCKER_PRE_MAKE_FAVORITE,
BLOODSUCKER_MAKE_FAVORITE,
BLOODSUCKER_MADE_VASSAL,
BLOODSUCKER_EXIT_TORPOR,
BLOODSUCKER_FINAL_DEATH,
))
remove_clan_objective()
bloodsuckerdatum = null
return ..()
///legacy code support
/datum/bloodsucker_clan/proc/get_clan()
return name
/datum/bloodsucker_clan/proc/give_clan_objective()
if(isnull(clan_objective))
return
clan_objective = new clan_objective()
clan_objective.objective_name = "Clan Objective"
clan_objective.owner = bloodsuckerdatum.owner
bloodsuckerdatum.objectives += clan_objective
bloodsuckerdatum.owner.announce_objectives()
/datum/bloodsucker_clan/proc/remove_clan_objective()
bloodsuckerdatum.objectives -= clan_objective
QDEL_NULL(clan_objective)
bloodsuckerdatum.owner.announce_objectives()
/**
* Called when a Bloodsucker exits Torpor
* args:
* source - the Bloodsucker exiting Torpor
*/
/datum/bloodsucker_clan/proc/on_exit_torpor(datum/antagonist/bloodsucker/source)
SIGNAL_HANDLER
/**
* Called when a Bloodsucker enters Final Death
* args:
* source - the Bloodsucker exiting Torpor
*/
/datum/bloodsucker_clan/proc/on_final_death(datum/antagonist/bloodsucker/source)
SIGNAL_HANDLER
return FALSE
/**
* Called during Bloodsucker's LifeTick
* args:
* bloodsuckerdatum - the antagonist datum of the Bloodsucker running this.
*/
/datum/bloodsucker_clan/proc/handle_clan_life(datum/antagonist/bloodsucker/source)
SIGNAL_HANDLER
/**
* Called when a Bloodsucker successfully Vassalizes someone.
* args:
* bloodsuckerdatum - the antagonist datum of the Bloodsucker running this.
*/
/datum/bloodsucker_clan/proc/on_vassal_made(datum/antagonist/bloodsucker/source, mob/living/user, mob/living/target)
SIGNAL_HANDLER
user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE)
target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE)
target.do_jitter_animation(15)
INVOKE_ASYNC(target, TYPE_PROC_REF(/mob, emote), "laugh")
/**
* Called when a Bloodsucker successfully starts spending their Rank
* args:
* bloodsuckerdatum - the antagonist datum of the Bloodsucker running this.
* target - The Vassal (if any) we are upgrading.
* cost_rank - TRUE/FALSE on whether this will cost us a rank when we go through with it.
* blood_cost - A number saying how much it costs to rank up
* ask - If they want to automatically spend the rest of their ranks
*/
/datum/bloodsucker_clan/proc/on_spend_rank(datum/antagonist/bloodsucker/source, mob/living/carbon/target, cost_rank = TRUE, blood_cost, ask)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(spend_rank), bloodsuckerdatum, cost_rank, blood_cost, ask)
/datum/bloodsucker_clan/proc/spend_rank(datum/antagonist/bloodsucker/source, cost_rank = TRUE, blood_cost, ask)
// Purchase Power Prompt
var/list/options = list()
for(var/datum/action/cooldown/bloodsucker/power as anything in bloodsuckerdatum.all_bloodsucker_powers)
if(initial(power.purchase_flags) & BLOODSUCKER_CAN_BUY && !(locate(power) in bloodsuckerdatum.powers))
options[initial(power.name)] = power
if(!LAZYLEN(options))
to_chat(bloodsuckerdatum.owner.current, span_notice("You grow more ancient by the night!"))
else
// Give them the UI to purchase a power.
var/choice = tgui_input_list(bloodsuckerdatum.owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...", options)
// Prevent Bloodsuckers from closing/reopning their coffin to spam Levels.
if(cost_rank && bloodsuckerdatum.bloodsucker_level_unspent <= 0)
return
// Did you choose a power?
if(!choice || !options[choice])
to_chat(bloodsuckerdatum.owner.current, span_notice("You prevent your blood from thickening just yet, but you may try again later."))
return
// Prevent Bloodsuckers from closing/reopning their coffin to spam Levels.
if(locate(options[choice]) in bloodsuckerdatum.powers)
to_chat(bloodsuckerdatum.owner.current, span_notice("You prevent your blood from thickening just yet, but you may try again later."))
return
// Prevent Bloodsuckers from purchasing a power while outside of their Coffin.
if(!istype(bloodsuckerdatum.owner.current.loc, /obj/structure/closet/crate/coffin))
to_chat(bloodsuckerdatum.owner.current, span_warning("You must be in your Coffin to purchase Powers."))
return
// Good to go - Buy Power!
var/datum/action/cooldown/bloodsucker/purchased_power = options[choice]
bloodsuckerdatum.BuyPower(new purchased_power)
bloodsuckerdatum.owner.current.balloon_alert(bloodsuckerdatum.owner.current, "learned [choice]!")
to_chat(bloodsuckerdatum.owner.current, span_notice("You have learned how to use [choice]!"))
finalize_spend_rank(bloodsuckerdatum, cost_rank, blood_cost, ask)
/datum/bloodsucker_clan/proc/finalize_spend_rank(datum/antagonist/bloodsucker/source, cost_rank = TRUE, blood_cost, ask)
bloodsuckerdatum.LevelUpPowers()
bloodsuckerdatum.bloodsucker_regen_rate += 0.05
bloodsuckerdatum.max_blood_volume += 100
// Misc. Stats Upgrades
if(ishuman(bloodsuckerdatum.owner.current))
var/mob/living/carbon/human/user = bloodsuckerdatum.owner.current
var/datum/species/user_species = user.dna.species
user_species.punchdamagelow += 0.5
// This affects the hitting power of Brawn.
user_species.punchdamagehigh += 0.5
// We're almost done - Spend your Rank now.
bloodsuckerdatum.bloodsucker_level++
if(cost_rank)
bloodsuckerdatum.bloodsucker_level_unspent--
if(blood_cost)
bloodsuckerdatum.AddBloodVolume(-blood_cost)
// Ranked up enough to get your true Reputation?
if(bloodsuckerdatum.bloodsucker_level == 4)
bloodsuckerdatum.SelectReputation(am_fledgling = FALSE, forced = TRUE)
to_chat(bloodsuckerdatum.owner.current, span_notice("You are now a rank [bloodsuckerdatum.bloodsucker_level] Bloodsucker. \
Your strength, health, feed rate, regen rate, and maximum blood capacity have all increased! \n\
* Your existing powers have all ranked up as well!"))
if(ask) //please no
bloodsuckerdatum.owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, TRUE, pressure_affected = FALSE)
bloodsuckerdatum.update_hud()
if(bloodsuckerdatum.bloodsucker_level_unspent && cost_rank)
if(ask)
if(tgui_alert(bloodsuckerdatum.owner.current, "You have leftover ranks, do you want to spend them all?", "Time Management Team", list("Yes", "No")) == "No")
return
spend_rank(bloodsuckerdatum, cost_rank, blood_cost, FALSE)
/**
* Called when we are trying to turn someone into a Favorite Vassal
* args:
* bloodsuckerdatum - the antagonist datum of the Bloodsucker performing this.
* vassaldatum - the antagonist datum of the Vassal being offered up.
*/
/datum/bloodsucker_clan/proc/on_offer_favorite(datum/antagonist/bloodsucker/source, datum/antagonist/vassal/vassaldatum)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(offer_favorite), bloodsuckerdatum, vassaldatum)
/datum/bloodsucker_clan/proc/offer_favorite(datum/antagonist/bloodsucker/source, datum/antagonist/vassal/vassaldatum)
if(vassaldatum.special_type)
to_chat(bloodsuckerdatum.owner.current, span_notice("This Vassal was already assigned a special position."))
return FALSE
if(!vassaldatum.owner.can_make_special(creator = bloodsuckerdatum.owner))
to_chat(bloodsuckerdatum.owner.current, span_notice("This Vassal is unable to gain a Special rank due to innate features."))
return FALSE
var/list/options = list()
var/list/radial_display = list()
for(var/datum/antagonist/vassal/vassaldatums as anything in subtypesof(/datum/antagonist/vassal))
if(bloodsuckerdatum.special_vassals[initial(vassaldatums.special_type)])
continue
options[initial(vassaldatums.name)] = vassaldatums
var/datum/radial_menu_choice/option = new
option.image = image(icon = initial(vassaldatums.hud_icon), icon_state = initial(vassaldatums.antag_hud_name))
option.info = "[initial(vassaldatums.name)] - [span_boldnotice(initial(vassaldatums.vassal_description))]"
radial_display[initial(vassaldatums.name)] = option
if(!options.len)
return
to_chat(bloodsuckerdatum.owner.current, span_notice("You can change who this Vassal is, who are they to you?"))
var/vassal_response = show_radial_menu(bloodsuckerdatum.owner.current, vassaldatum.owner.current, radial_display)
if(!vassal_response)
return
vassal_response = options[vassal_response]
if(QDELETED(src) || QDELETED(bloodsuckerdatum.owner.current) || QDELETED(vassaldatum.owner.current))
return FALSE
vassaldatum.make_special(vassal_response)
bloodsuckerdatum.bloodsucker_blood_volume -= 150
/**
* Called when we are successfully turn a Vassal into a Favorite Vassal
* args:
* bloodsuckerdatum - antagonist datum of the Bloodsucker who turned them into a Vassal.
* vassaldatum - the antagonist datum of the Vassal being offered up.
*/
/datum/bloodsucker_clan/proc/on_favorite_vassal(datum/antagonist/bloodsucker/source, datum/antagonist/vassal/vassaldatum)
SIGNAL_HANDLER
vassaldatum.BuyPower(new /datum/action/cooldown/bloodsucker/targeted/brawn)