|
15 | 15 | throw_speed = 3
|
16 | 16 | throw_range = 7
|
17 | 17 | override_notes = TRUE
|
| 18 | + |
| 19 | + ///String, used for checking if ammo of different types but still fits can fit inside it; generally used for magazines |
| 20 | + var/caliber |
| 21 | + |
18 | 22 | ///list containing the actual ammo within the magazine
|
19 | 23 | var/list/stored_ammo = list()
|
20 | 24 | ///type that the magazine will be searching for, rejects if not a subtype of
|
21 | 25 | var/ammo_type = /obj/item/ammo_casing
|
22 | 26 | ///maximum amount of ammo in the magazine
|
23 | 27 | var/max_ammo = 7
|
| 28 | + |
24 | 29 | ///Controls how sprites are updated for the ammo box; see defines in combat.dm: AMMO_BOX_ONE_SPRITE; AMMO_BOX_PER_BULLET; AMMO_BOX_FULL_EMPTY
|
25 | 30 | var/multiple_sprites = AMMO_BOX_ONE_SPRITE
|
26 | 31 | ///For sprite updating, do we use initial(icon_state) or base_icon_state?
|
27 | 32 | var/multiple_sprite_use_base = FALSE
|
28 |
| - ///String, used for checking if ammo of different types but still fits can fit inside it; generally used for magazines |
29 |
| - var/caliber |
30 |
| - ///Allows multiple bullets to be loaded in from one click of another box/magazine |
31 |
| - var/multiload = TRUE |
| 33 | + |
| 34 | + ///Delay for loading bullets in. |
| 35 | + var/load_delay = 0.5 SECONDS |
32 | 36 | ///Whether the magazine should start with nothing in it
|
33 | 37 | var/start_empty = FALSE
|
| 38 | + |
34 | 39 | ///cost of all the bullets in the magazine/box
|
35 | 40 | var/list/bullet_cost
|
36 | 41 | ///cost of the materials in the magazine/box itself
|
|
41 | 46 | if(!bullet_cost)
|
42 | 47 | base_cost = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1)
|
43 | 48 | bullet_cost = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.9 / max_ammo)
|
| 49 | + |
44 | 50 | if(!start_empty)
|
45 | 51 | top_off(starting=TRUE)
|
46 | 52 |
|
|
102 | 108 | /obj/item/ammo_box/proc/can_load(mob/user)
|
103 | 109 | return TRUE
|
104 | 110 |
|
105 |
| -/obj/item/ammo_box/attackby(obj/item/A, mob/user, params, silent = FALSE, replace_spent = 0) |
106 |
| - var/num_loaded = 0 |
107 |
| - if(!can_load(user)) |
108 |
| - return |
109 |
| - if(istype(A, /obj/item/ammo_box)) |
110 |
| - var/obj/item/ammo_box/AM = A |
111 |
| - for(var/obj/item/ammo_casing/AC in AM.stored_ammo) |
112 |
| - var/did_load = give_round(AC, replace_spent) |
113 |
| - if(did_load) |
114 |
| - AM.stored_ammo -= AC |
115 |
| - num_loaded++ |
116 |
| - if(!did_load || !multiload) |
117 |
| - break |
118 |
| - if(num_loaded) |
119 |
| - AM.update_ammo_count() |
120 |
| - if(isammocasing(A)) |
121 |
| - var/obj/item/ammo_casing/AC = A |
122 |
| - if(give_round(AC, replace_spent)) |
123 |
| - user.transferItemToLoc(AC, src, TRUE) |
124 |
| - num_loaded++ |
125 |
| - AC.update_appearance() |
126 |
| - |
127 |
| - if(num_loaded) |
128 |
| - if(!silent) |
129 |
| - to_chat(user, span_notice("You load [num_loaded] shell\s into \the [src]!")) |
130 |
| - playsound(src, 'sound/weapons/gun/general/mag_bullet_insert.ogg', 60, TRUE) |
131 |
| - update_ammo_count() |
132 |
| - |
133 |
| - return num_loaded |
| 111 | +/obj/item/ammo_box/attackby(obj/item/A, mob/user, params) |
| 112 | + return attempt_load_round(A, user) |
134 | 113 |
|
135 | 114 | /obj/item/ammo_box/attack_self(mob/user)
|
136 | 115 | var/obj/item/ammo_casing/A = get_round()
|
|
144 | 123 | to_chat(user, span_notice("You remove a round from [src]!"))
|
145 | 124 | update_ammo_count()
|
146 | 125 |
|
| 126 | +/// Attempts to load a given item into this ammo box |
| 127 | +/obj/item/ammo_box/proc/attempt_load_round(obj/item/I, mob/user, silent = FALSE, replace_spent = FALSE) |
| 128 | + var/num_loaded = 0 |
| 129 | + if(!can_load(user)) |
| 130 | + return FALSE |
| 131 | + |
| 132 | + if(istype(I, /obj/item/ammo_box)) |
| 133 | + var/obj/item/ammo_box/AM = I |
| 134 | + for(var/obj/item/ammo_casing/AC in AM.stored_ammo) |
| 135 | + if(user && load_delay && !do_after(user, src, load_delay, IGNORE_USER_LOC_CHANGE, FALSE, interaction_key = "load_round")) |
| 136 | + break |
| 137 | + |
| 138 | + var/did_load = give_round(AC, replace_spent) |
| 139 | + if(!did_load) |
| 140 | + break |
| 141 | + |
| 142 | + AM.stored_ammo -= AC |
| 143 | + num_loaded++ |
| 144 | + if(!silent) |
| 145 | + user?.visible_message( |
| 146 | + span_notice("[user] loads a round into [src]."), |
| 147 | + vision_distance = COMBAT_MESSAGE_RANGE, |
| 148 | + ) |
| 149 | + playsound(src, 'sound/weapons/gun/general/mag_bullet_insert.ogg', 60, TRUE) |
| 150 | + update_ammo_count() |
| 151 | + AM.update_ammo_count() |
| 152 | + |
| 153 | + if(isammocasing(I)) |
| 154 | + var/obj/item/ammo_casing/AC = I |
| 155 | + if(give_round(AC, replace_spent)) |
| 156 | + user.transferItemToLoc(AC, src, TRUE) |
| 157 | + num_loaded++ |
| 158 | + if(!silent) |
| 159 | + playsound(src, 'sound/weapons/gun/general/mag_bullet_insert.ogg', 60, TRUE) |
| 160 | + update_ammo_count() |
| 161 | + |
| 162 | + return num_loaded |
| 163 | + |
147 | 164 | /// Updates the materials and appearance of this ammo box
|
148 | 165 | /obj/item/ammo_box/proc/update_ammo_count()
|
149 | 166 | update_custom_materials()
|
150 | 167 | update_appearance()
|
151 | 168 |
|
152 |
| -/obj/item/ammo_box/update_desc(updates) |
| 169 | +/obj/item/ammo_box/examine(mob/user) |
153 | 170 | . = ..()
|
154 |
| - var/shells_left = LAZYLEN(stored_ammo) |
155 |
| - desc = "[initial(desc)] There [(shells_left == 1) ? "is" : "are"] [shells_left] shell\s left!" |
| 171 | + . += span_notice(get_ammo_desc()) |
156 | 172 |
|
157 | 173 | /obj/item/ammo_box/update_icon_state()
|
158 | 174 | var/shells_left = LAZYLEN(stored_ammo)
|
|
170 | 186 | temp_materials[material] = (bullet_cost[material] * stored_ammo.len) + base_cost[material]
|
171 | 187 | set_custom_materials(temp_materials)
|
172 | 188 |
|
| 189 | +/// Returns a string that describes the amount of ammo in the magazine. |
| 190 | +/obj/item/ammo_box/proc/get_ammo_desc(exact) |
| 191 | + if(exact) |
| 192 | + return "There are [ammo_count(TRUE)] rounds in [src]." |
| 193 | + |
| 194 | + var/ammo_count = ammo_count(TRUE) |
| 195 | + if(ammo_count == 1) |
| 196 | + return "There is one round left." |
| 197 | + |
| 198 | + var/ammo_percent = ceil(((ammo_count / max_ammo) * 100)) |
| 199 | + |
| 200 | + switch(ammo_percent) |
| 201 | + if(0) |
| 202 | + return "It is empty." |
| 203 | + if(1 to 20) |
| 204 | + return "It rattles when you shake it." |
| 205 | + if(21 to 40) |
| 206 | + return "It is running low on rounds." |
| 207 | + if(41 to 69) |
| 208 | + return "It is about half full." |
| 209 | + if(70 to 99) |
| 210 | + return "It is mostly full." |
| 211 | + if(100) |
| 212 | + return "It is fully loaded." |
| 213 | + |
173 | 214 | ///Count of number of bullets in the magazine
|
174 |
| -/obj/item/ammo_box/magazine/proc/ammo_count(countempties = TRUE) |
| 215 | +/obj/item/ammo_box/proc/ammo_count(countempties = TRUE) |
175 | 216 | var/boolets = 0
|
176 | 217 | for(var/obj/item/ammo_casing/bullet in stored_ammo)
|
177 | 218 | if(bullet && (bullet.loaded_projectile || countempties))
|
|
0 commit comments