-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathatom_defense.dm
145 lines (122 loc) · 5.83 KB
/
atom_defense.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
/// The essential proc to call when an atom must receive damage of any kind.
/atom/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0)
if(!uses_integrity)
CRASH("[src] had /atom/proc/take_damage() called on it without it being a type that has uses_integrity = TRUE!")
if(QDELETED(src))
CRASH("[src] taking damage after deletion")
if(atom_integrity <= 0)
CRASH("[src] taking damage while having <= 0 integrity")
if(sound_effect)
play_attack_sound(damage_amount, damage_type, damage_flag)
if(resistance_flags & INDESTRUCTIBLE)
return
damage_amount = run_atom_armor(damage_amount, damage_type, damage_flag, attack_dir, armour_penetration)
if(damage_amount < DAMAGE_PRECISION)
return
if(SEND_SIGNAL(src, COMSIG_ATOM_TAKE_DAMAGE, damage_amount, damage_type, damage_flag, sound_effect, attack_dir, armour_penetration) & COMPONENT_NO_TAKE_DAMAGE)
return
. = damage_amount
update_integrity(atom_integrity - damage_amount)
//BREAKING FIRST
if(integrity_failure && atom_integrity <= integrity_failure)
atom_break(damage_flag)
//DESTROYING SECOND
if(atom_integrity <= 0)
atom_destruction(damage_flag)
/// Proc for recovering atom_integrity. Returns the amount repaired by
/atom/proc/repair_damage(amount)
if(amount <= 0) // We only recover here
return
var/new_integrity = min(max_integrity, atom_integrity + amount)
. = new_integrity - atom_integrity
update_integrity(new_integrity)
if(integrity_failure && atom_integrity > integrity_failure)
atom_fix()
/// Handles the integrity of an atom changing. This must be called instead of changing integrity directly.
/atom/proc/update_integrity(new_value)
SHOULD_NOT_OVERRIDE(TRUE)
if(!uses_integrity)
CRASH("/atom/proc/update_integrity() was called on [src] when it doesnt use integrity!")
var/old_value = atom_integrity
new_value = max(0, new_value)
if(atom_integrity == new_value)
return
atom_integrity = new_value
SEND_SIGNAL(src, COMSIG_ATOM_INTEGRITY_CHANGED, old_value, new_value)
/// This mostly exists to keep atom_integrity private. Might be useful in the future.
/atom/proc/get_integrity()
SHOULD_BE_PURE(TRUE)
return atom_integrity
///returns the damage value of the attack after processing the atom's various armor protections
/atom/proc/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration = 0)
if(!uses_integrity)
CRASH("/atom/proc/run_atom_armor was called on [src] without being implemented as a type that uses integrity!")
if(damage_flag == MELEE && damage_amount < damage_deflection)
return 0
if(damage_type != BRUTE && damage_type != BURN)
return 0
var/armor_protection = 0
if(damage_flag)
armor_protection = armor.getRating(damage_flag)
if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor.
armor_protection = clamp(armor_protection - armour_penetration, min(armor_protection, 0), 100)
return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION)
///the sound played when the atom is damaged.
/atom/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
if(damage_amount)
playsound(src, 'sound/weapons/smash.ogg', 50, TRUE)
else
playsound(src, 'sound/weapons/tap.ogg', 50, TRUE)
if(BURN)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
///Called to get the damage that hulks will deal to the atom.
/atom/proc/hulk_damage()
return 150 //the damage hulks do on punches to this atom, is affected by melee armor
/atom/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0) //used by attack_alien, attack_animal, and attack_slime
if(!uses_integrity)
CRASH("unimplemented /atom/proc/attack_generic()!")
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
return take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user), armor_penetration)
/// Called when the atom is hit by a tesla bolt.
/atom/proc/tesla_act(source, power, zap_range, tesla_flags, list/shocked_targets)
if(HAS_TRAIT(src, TRAIT_TESLA_IGNORE))
return FALSE
if(!(tesla_flags & TESLA_ALLOW_DUPLICATES))
ADD_TRAIT(src, TRAIT_TESLA_IGNORE, WAS_SHOCKED)
addtimer(CALLBACK(src, PROC_REF(reset_shocked)), 10)
if(power < TESLA_MINI_POWER) //tesla bolts bounce twice, tesla miniball bolts bounce only once
return TRUE
if(!(tesla_flags & TESLA_NO_CHAINING) && power >= 1500 && zap_range > 3)
tesla_zap(src, zap_range - 1, power * 0.67, tesla_flags, shocked_targets)
return TRUE
/atom/proc/reset_shocked()
REMOVE_TRAIT(src, TRAIT_TESLA_IGNORE, WAS_SHOCKED)
/// Called after the atom takes damage and integrity is below integrity_failure level
/atom/proc/atom_break(damage_flag)
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_BREAK)
/// Called when integrity is repaired above the breaking point having been broken before
/atom/proc/atom_fix()
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_FIX)
///what happens when the atom's integrity reaches zero.
/atom/proc/atom_destruction(damage_flag)
return
///changes max_integrity while retaining current health percentage, returns TRUE if the atom got broken.
/atom/proc/modify_max_integrity(new_max, can_break = TRUE, damage_type = BRUTE)
if(!uses_integrity)
CRASH("/atom/proc/modify_max_integrity() was called on [src] when it doesnt use integrity!")
var/current_integrity = atom_integrity
var/current_max = max_integrity
if(current_integrity != 0 && current_max != 0)
var/percentage = current_integrity / current_max
current_integrity = max(1, round(percentage * new_max)) //don't destroy it as a result
atom_integrity = current_integrity
max_integrity = new_max
if(can_break && integrity_failure && current_integrity <= integrity_failure)
atom_break(damage_type)
return TRUE
return FALSE