-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathmouse.dm
369 lines (325 loc) · 12 KB
/
mouse.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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
GLOBAL_LIST_INIT(mouse_comestible, typecacheof(list(
/obj/effect/decal/cleanable/food,
/obj/effect/decal/cleanable/greenglow,
/obj/effect/decal/cleanable/insectguts,
/obj/effect/decal/cleanable/vomit,
/obj/item/trash,
/obj/item/grown/bananapeel,
/obj/item/grown/corncob,
/obj/item/grown/sunflower,
/obj/item/cigbutt
)))
GLOBAL_VAR_INIT(food_for_next_mouse, 0)
GLOBAL_VAR_INIT(mouse_food_eaten, 0)
GLOBAL_VAR_INIT(mouse_spawned, 0)
GLOBAL_VAR_INIT(mouse_killed, 0)
#define FOODPERMOUSE 35
/mob/living/simple_animal/mouse
name = "mouse"
desc = "This cute little guy just loves the taste of uninsulated electrical cables. Isn't he adorable?"
icon_state = "mouse_gray"
icon_living = "mouse_gray"
icon_dead = "mouse_gray_dead"
speak = list("Squeak!","SQUEAK!","Squeak?")
speak_emote = list("squeaks")
emote_hear = list("squeaks.")
emote_see = list("runs in a circle.", "shakes.")
speak_chance = 1
turns_per_move = 5
maxHealth = 5
health = 5
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/mouse = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "splats"
density = FALSE
ventcrawler = VENTCRAWLER_ALWAYS
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BEAST
lighting_cutoff = LIGHTING_CUTOFF_HIGH
can_be_held = TRUE //mouse gaming
worn_slot_flags = ITEM_SLOT_HEAD
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
move_force = MOVE_FORCE_EXTREMELY_WEAK
faction = list("neutral", "rat") //while they aren't rats, we don't want ai controlled rats killing these because rat king can convert them
var/chew_probability = 1
var/full = FALSE
var/eating = FALSE
var/cheesed = FALSE
var/cheese_time = 0
var/food_type = /obj/item/reagent_containers/food/snacks/deadmouse
/mob/living/simple_animal/mouse/Initialize(mapload)
. = ..()
AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100)
if(!body_color)
body_color = pick( list("brown","gray","white") )
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
/mob/living/simple_animal/mouse/handle_stomach()
if(cheesed && cheese_time < world.time)
cheese_down()
/mob/living/simple_animal/mouse/proc/splat()
if(key)
adjustHealth(rand(7,12))
if(health <= 0)
src.icon_dead = "mouse_[body_color]_splat"
else
src.health = 0
src.icon_dead = "mouse_[body_color]_splat"
death()
/mob/living/simple_animal/mouse/death(gibbed, toast)
GLOB.mouse_killed++
if(!ckey)
..(1)
if(!gibbed)
var/obj/item/reagent_containers/food/snacks/deadmouse/M = new food_type(loc)
M.icon_state = icon_dead
M.name = name
if(toast)
M.add_atom_colour("#3A3A3A", FIXED_COLOUR_PRIORITY)
M.desc = "It's toast."
qdel(src)
else
SSmobs.cheeserats -= src
..(gibbed)
/mob/living/simple_animal/mouse/Crossed(atom/movable/AM)
if(ishuman(AM))
if(!stat)
var/mob/M = AM
to_chat(M, span_notice("[icon2html(src, M)] Squeak!"))
return ..()
/mob/living/simple_animal/mouse/handle_automated_action()
if(prob(chew_probability))
var/turf/open/floor/F = get_turf(src)
if(istype(F) && !F.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
var/obj/structure/cable/C = locate() in F
if(C && prob(15))
if(C.avail())
visible_message(span_warning("[src] chews through the [C]. It's toast!"))
playsound(src, 'sound/effects/sparks2.ogg', 100, TRUE)
C.deconstruct()
death(toast=1)
else
C.deconstruct()
visible_message(span_warning("[src] chews through the [C]."))
var/obj/structure/ethernet_cable/E = locate() in F
if(E && prob(15))
E.deconstruct()
visible_message(span_warning("[src] chews through the [E]."))
for(var/obj/item/reagent_containers/food/snacks/cheesewedge/cheese in range(1, src))
if(prob(10))
be_fruitful()
qdel(cheese)
return
for(var/obj/item/reagent_containers/food/snacks/royalcheese/bigcheese in range(1, src))
qdel(bigcheese)
evolve()
return
/**
*Checks the mouse cap, if it's above the cap, doesn't spawn a mouse. If below, spawns a mouse and adds it to cheeserats.
*/
/mob/living/simple_animal/mouse/proc/be_fruitful()
var/cap = CONFIG_GET(number/ratcap)
if(LAZYLEN(SSmobs.cheeserats) >= cap)
visible_message(span_warning("[src] carefully eats the cheese, hiding it from the [cap] mice on the station!"))
return
var/mob/living/newmouse = new /mob/living/simple_animal/mouse(loc)
SSmobs.cheeserats += newmouse
visible_message(span_notice("[src] nibbles through the cheese, attracting another mouse!"))
/**
*Spawns a new regal rat, says some good jazz, and if sentient, transfers the relivant mind.
*/
/mob/living/simple_animal/mouse/proc/evolve()
var/mob/living/simple_animal/hostile/regalrat/rat = new(get_turf(src))
if(mind)
mind.transfer_to(rat)
qdel(src)
visible_message(span_warning("[src] devours the cheese! He morphs into something... greater!"))
rat.say("RISE, MY SUBJECTS! SCREEEEEEE!")
/mob/living/simple_animal/mouse/Move()
. = ..()
if(stat != CONSCIOUS)
return .
if(!key)
eat_cheese()
else
if(!(locate(/obj/structure/table) in get_turf(src)))
for(var/obj/item/reagent_containers/glass/G in get_turf(src))
G.throw_at(get_turf(G), 0, 1, src)
for(var/obj/item/reagent_containers/food/drinks/D in get_turf(src))
D.throw_at(get_turf(D), 0, 1, src)
/mob/living/simple_animal/mouse/proc/eat_cheese()
var/obj/item/reagent_containers/food/snacks/cheesewedge/CW = locate(/obj/item/reagent_containers/food/snacks/cheesewedge) in loc
if(!QDELETED(CW) && full == FALSE)
say("Burp!")
visible_message(span_warning("[src] gobbles up the [CW]."))
qdel(CW)
full = TRUE
addtimer(VARSET_CALLBACK(src, full, FALSE), 3 MINUTES)
/mob/living/simple_animal/mouse/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/reagent_containers/food/snacks/cheesewedge))
to_chat(user, span_notice("You feed [O] to [src]."))
visible_message("[src] squeaks happily!")
qdel(O)
else
return ..()
/mob/living/simple_animal/mouse/attack_ghost(mob/dead/observer/user)
if(client)
return ..()
if(stat == DEAD)
return ..()
user.possess_mouse(src)
/mob/living/simple_animal/mouse/start_pulling(atom/movable/AM, state, force, supress_message)
return FALSE
/mob/living/simple_animal/mouse/CtrlClickOn(atom/A)
. = TRUE
face_atom(A)
if(!isturf(loc))
return
if(next_move > world.time)
return
if(!A.Adjacent(src))
return
if(!can_eat(A))
return FALSE
eating = TRUE
layer = MOB_LAYER
visible_message(span_danger("[src] starts eating away [A]..."),span_notice("You start eating the [A]..."))
if(do_after(src, 3 SECONDS, A, timed_action_flags = IGNORE_HELD_ITEM))
if(QDELETED(A))
return
visible_message(span_danger("[src] finishes eating up [A]!"),span_notice("You finish up eating [A]."))
mouse_eat(A)
playsound(A.loc,'sound/effects/mousesqueek.ogg', 100) // i have no idea how loud this is, 100 seems to be used for the squeak component
GLOB.mouse_food_eaten++
eating = FALSE
layer = BELOW_OPEN_DOOR_LAYER
/mob/living/simple_animal/mouse/proc/can_eat(atom/A)
. = FALSE
if(eating)
return FALSE
if(is_type_in_list(A, GLOB.mouse_comestible))
return TRUE
if(istype(A, /obj/item/reagent_containers/food) && !(locate(/obj/structure/table) in get_turf(A)))
return TRUE
/mob/living/simple_animal/mouse/proc/regen_health(amt = 5)
var/overheal = max(health + amt - maxHealth, 0)
adjustHealth(-amt)
GLOB.food_for_next_mouse += overheal
var/mice = FLOOR(GLOB.food_for_next_mouse / FOODPERMOUSE, 1)
if(!mice)
return
GLOB.mouse_spawned += mice
GLOB.food_for_next_mouse = max(GLOB.food_for_next_mouse - FOODPERMOUSE * mice, 0)
SSminor_mapping.trigger_migration(mice, TRUE)
/mob/living/simple_animal/mouse/proc/cheese_up()
regen_health(15)
if(cheesed)
cheese_time += 3 MINUTES
return
cheesed = TRUE
resize = 2
update_transform()
add_movespeed_modifier(MOVESPEED_ID_MOUSE_CHEESE, TRUE, 100, multiplicative_slowdown = -1)
maxHealth = 30
health = maxHealth
to_chat(src, span_userdanger("You ate cheese! You are now stronger, bigger and faster!"))
cheese_time = world.time + 3 MINUTES
/mob/living/simple_animal/mouse/proc/cheese_down()
cheesed = FALSE
maxHealth = 15
health = maxHealth
resize = 0.5
update_transform()
remove_movespeed_modifier(MOVESPEED_ID_MOUSE_CHEESE, TRUE)
to_chat(src, span_userdanger("A feeling of sadness comes over you as the effects of the cheese wears off. You. Must. Get. More."))
/mob/living/simple_animal/mouse/proc/mouse_eat(obj/item/reagent_containers/food/snacks/F)
var/list/cheeses = list(/obj/item/reagent_containers/food/snacks/cheesewedge, /obj/item/reagent_containers/food/snacks/cheesewheel,
/obj/item/reagent_containers/food/snacks/store/cheesewheel, /obj/item/reagent_containers/food/snacks/customizable/cheesewheel,
/obj/item/reagent_containers/food/snacks/cheesiehonkers) //all cheeses - royal
if(istype(F, /obj/item/reagent_containers/food/snacks/royalcheese))
evolve()
if(istype(F, /obj/item/grown/bananapeel/bluespace))
var/obj/item/grown/bananapeel/bluespace/B = F
var/teleport_radius = max(round(B.seed.potency / 10), 1)
var/turf/T = get_turf(src)
do_teleport(src, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE)
if(is_type_in_list(F, cheeses))
cheese_up()
regen_health()
qdel(F)
/*
* Mouse types
*/
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
name = "Tom"
desc = "Jerry the cat is not amused."
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "splats"
gold_core_spawnable = NO_SPAWN
/mob/living/simple_animal/mouse/fat
name = "fat mouse"
desc = "This cute \"little\" guy seems to have been snacking on too much cheddar. Isn't he adorable?"
body_color = "fat" //what colour are you? FAT
icon_state = "mouse_fat"
turns_per_move = 10
maxHealth = 10
health = 10
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/mouse/fat = 1)
food_type = /obj/item/reagent_containers/food/snacks/deadmouse/fat
/obj/item/reagent_containers/food/snacks/deadmouse
name = "dead mouse"
desc = "It looks like somebody dropped the bass on it. A Lizard's favorite meal."
icon = 'icons/mob/animal.dmi'
icon_state = "mouse_gray_dead"
bitesize = 3
eatverb = "devour"
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2)
foodtype = MICE
grind_results = list(/datum/reagent/blood = 20, /datum/reagent/liquidgibs = 5)
var/meat_type = /obj/item/reagent_containers/food/snacks/meat/slab/mouse
/obj/item/reagent_containers/food/snacks/deadmouse/fat
name = "dead fat mouse"
desc = "It looks like somebody dropped the bass on it. A Lizard's favorite meal."
icon_state = "mouse_fat_dead"
list_reagents = list(/datum/reagent/consumable/nutriment = 5) //same amount of food, but it's not healthy
junkiness = 25
foodtype = MICE | JUNKFOOD
meat_type = /obj/item/reagent_containers/food/snacks/meat/slab/mouse/fat
/obj/item/reagent_containers/food/snacks/deadmouse/attackby(obj/item/I, mob/living/user, params)
if(I.is_sharp() && user.combat_mode)
if(isturf(loc))
new meat_type(loc)
to_chat(user, span_notice("You butcher [src]."))
qdel(src)
else
to_chat(user, span_warning("You need to put [src] on a surface to butcher it!"))
else
return ..()
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
/mob/living/simple_animal/mouse/Destroy()
SSmobs.cheeserats -= src
return ..()
/mob/living/simple_animal/mouse/revive(full_heal = FALSE, admin_revive = FALSE)
var/cap = CONFIG_GET(number/ratcap)
if(!admin_revive && !ckey && LAZYLEN(SSmobs.cheeserats) >= cap)
visible_message(span_warning("[src] twitched but does not continue moving due to the overwhelming rodent population on the station!"))
return FALSE
. = ..()
if(.)
SSmobs.cheeserats += src