diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index b0fdab9f3d0..9f21dbcd2ce 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -3,7 +3,7 @@ var/global/list/space_surprises = list( /obj/item/clothing/mask/facehugger = /obj/item/weapon/pickaxe/silver =4, /obj/item/weapon/pickaxe/drill =4, /obj/item/weapon/pickaxe/jackhammer =4, - /mob/living/simple_animal/carp =3, + //mob/living/simple_animal/hostile/carp =3, /obj/item/weapon/pickaxe/diamond =3, /obj/item/weapon/pickaxe/diamonddrill =3, /obj/item/weapon/pickaxe/gold =3, diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index fc03ff5ad65..f195b295cb1 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -502,15 +502,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", if (C>=26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist - switch(alert("The cloth of reality can't take that much of a strain. By creating another rune, you risk locally tearing reality apart, which would prove fatal to you. Do you still wish to scribe the rune?",,"Yes","No")) - if("Yes") - if(prob(C*5-105-(runedec-ticker.mode.cult.len)*5)) //including the useless rune at the secret room, shouldn't count against the limit - Urist - usr.emote("scream") - user << "\red A tear momentarily appears in reality. Before it closes, you catch a glimpse of that which lies beyond. That proves to be too much for your mind." - usr.gib() - return - if("No") - return + alert("The cloth of reality can't take that much of a strain. Remove some runes first!") + return else switch(alert("You open the tome",,"Read it","Scribe a rune", "Notes")) //Fuck the "Cancel" option. Rewrite the whole tome interface yourself if you want it to work better. And input() is just ugly. - K0000 if("Cancel") diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index 43baff66d91..84d27760515 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -367,7 +367,7 @@ /proc/carp_migration() // -- Darem for(var/obj/effect/landmark/C in landmarks_list) if(C.name == "carpspawn") - new /mob/living/simple_animal/carp(C.loc) + new /mob/living/simple_animal/hostile/carp(C.loc) //sleep(100) spawn(rand(300, 600)) //Delayed announcements to keep the crew on their toes. command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") diff --git a/code/game/machinery/camera/wires.dm b/code/game/machinery/camera/wires.dm index 3aa9ed59056..3145a5d156f 100644 --- a/code/game/machinery/camera/wires.dm +++ b/code/game/machinery/camera/wires.dm @@ -50,7 +50,7 @@ if(CAMERA_WIRE_POWER) deactivate(usr, 1) - shock(usr) + //shock(usr) if(CAMERA_WIRE_LIGHT) light_disabled = 1 diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 5c6b9ea6b07..85594df4f2b 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -293,7 +293,7 @@ for(var/obj/effect/decal/cleanable/blood/B in linkedholodeck) del(B) - for(var/mob/living/simple_animal/carp/C in linkedholodeck) + for(var/mob/living/simple_animal/hostile/carp/C in linkedholodeck) del(C) holographic_items = A.copy_contents_to(linkedholodeck , 1) @@ -314,7 +314,7 @@ T.temperature = 5000 T.hotspot_expose(50000,50000,1) if(L.name=="Holocarp Spawn") - new /mob/living/simple_animal/carp(L.loc) + new /mob/living/simple_animal/hostile/carp(L.loc) /obj/machinery/computer/HolodeckControl/proc/emergencyShutdown() diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index fe15703fa2a..9f911085228 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -47,6 +47,6 @@ /obj/item/weapon/grenade/spawnergrenade/spesscarp name = "carp delivery grenade" - spawner_type = /mob/living/simple_animal/carp + spawner_type = /mob/living/simple_animal/hostile/carp deliveryamt = 5 origin_tech = "materials=3;magnets=4;syndicate=4" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bear.dm b/code/modules/mob/living/simple_animal/bear.dm deleted file mode 100644 index bcf34041387..00000000000 --- a/code/modules/mob/living/simple_animal/bear.dm +++ /dev/null @@ -1,186 +0,0 @@ -#define BEAR_STANCE_IDLE 1 -#define BEAR_STANCE_ALERT 2 -#define BEAR_STANCE_ATTACK 3 -#define BEAR_STANCE_ATTACKING 4 -#define BEAR_STANCE_TIRED 5 - -//Space bears! -/mob/living/simple_animal/bear - name = "space bear" - desc = "RawrRawr!!" - icon_state = "bear" - icon_living = "bear" - icon_dead = "bear_dead" - icon_gib = "bear_gib" - speak = list("RAWR!","Rawr!","GRR!","Growl!") - speak_emote = list("growls", "roars") - emote_hear = list("rawrs","grumbles","grawls") - emote_see = list("stares ferociously", "stomps") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "pokes the" - stop_automated_movement_when_pulled = 0 - maxHealth = 60 - health = 60 - melee_damage_lower = 20 - melee_damage_upper = 30 - - //Space bears aren't affected by atmos. - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - - var/stance = BEAR_STANCE_IDLE //Used to determine behavior - var/stance_step = 0 //Used to delay checks depending on what stance the bear is in - var/mob/living/target_mob //Once the bear enters attack stance, it will try to chase this mob. This it to prevent it changing it's mind between multiple mobs. - -//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! -/mob/living/simple_animal/bear/Hudson - name = "Hudson" - desc = "" - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "pokes" - -/mob/living/simple_animal/bear/Life() - ..() - - if(client) return //Player controlled bears shouldnt be processing AI stuff - - if(stat) - walk(src,0)//Stops the movement - - if(!stat) - if(loc && istype(loc,/turf/space)) - icon_state = "bear" - else - icon_state = "bearfloor" - - switch(stance) - if(BEAR_STANCE_IDLE) - stop_automated_movement = 0 - stance_step++ - if(stance_step > 5) - stance_step = 0 - for(var/atom/A in view(7,src)) - if(isbear(A)) - continue - - if(isliving(A)) - var/mob/living/L = A - if(!L.stat) - stance = BEAR_STANCE_ATTACK - target_mob = L - break - - if(istype(A, /obj/mecha)) - var/obj/mecha/M = A - if (M.occupant) - stance = BEAR_STANCE_ATTACK - target_mob = M - break - if (target_mob) - emote("stares alertly at [target_mob]") - - if(BEAR_STANCE_ALERT) - stop_automated_movement = 1 - var/found_mob = 0 - if(target_mob in view(7,src)) - if(target_mob && !(SA_attackable(target_mob))) - stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again. - stance_step++ - found_mob = 1 - src.dir = get_dir(src,target_mob) //Keep staring at the mob - - if(stance_step in list(1,4,7)) //every 3 ticks - var/action = pick( list( "growls at [target_mob]", "stares angrily at [target_mob]", "prepares to attack [target_mob]", "closely watches [target_mob]" ) ) - if(action) - emote(action) - if(!found_mob) - stance_step-- - - if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode - stance = BEAR_STANCE_IDLE - if(stance_step >= 7) //If we have been staring at a mob for 7 ticks, - stance = BEAR_STANCE_ATTACK - if(BEAR_STANCE_ATTACK) //This one should only be active for one tick, - stop_automated_movement = 1 - if(!target_mob || SA_attackable(target_mob)) - stance = BEAR_STANCE_ALERT - stance_step = 5 //Make it very alert, so it quickly attacks again if a mob returns - if(target_mob in view(7,src)) - walk_to(src, target_mob, 1, 3) - stance = BEAR_STANCE_ATTACKING - stance_step = 0 - if(BEAR_STANCE_ATTACKING) - - stop_automated_movement = 1 - stance_step++ - if(!target_mob || SA_attackable(target_mob)) - stance = BEAR_STANCE_ALERT - stance_step = 5 //Make it very alert, so it quickly attacks again if a mob returns - return - if(!(target_mob in view(7,src))) - stance = BEAR_STANCE_ALERT - stance_step = 5 //Make it very alert, so it quickly attacks again if a mob returns - target_mob = null - return - if(get_dist(src, target_mob) <= 1) //Attacking - emote( pick( list("slashes at [target_mob]", "bites [target_mob]") ) ) - - var/damage = rand(20,30) - - if(ishuman(target_mob)) - var/mob/living/carbon/human/H = target_mob - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") - var/datum/organ/external/affecting = H.get_organ(ran_zone(dam_zone)) - H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee")) - else if(isliving(target_mob)) - var/mob/living/L = target_mob - L.adjustBruteLoss(damage) - else if(istype(target_mob,/obj/mecha)) - var/obj/mecha/M = target_mob - M.attack_animal(src) - - if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest - emote( "is worn out and needs to rest" ) - stance = BEAR_STANCE_TIRED - stance_step = 0 - walk(src, 0) //This stops the bear's walking - return - if(BEAR_STANCE_TIRED) - stop_automated_movement = 1 - stance_step++ - if(stance_step >= 10) //rests for 10 ticks - if(target_mob && target_mob in view(7,src)) - stance = BEAR_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle. - else - stance = BEAR_STANCE_IDLE - - -/mob/living/simple_animal/bear/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(stance != BEAR_STANCE_ATTACK && stance != BEAR_STANCE_ATTACKING) - stance = BEAR_STANCE_ALERT - stance_step = 6 - target_mob = user - ..() - -/mob/living/simple_animal/bear/attack_hand(mob/living/carbon/human/M as mob) - if(stance != BEAR_STANCE_ATTACK && stance != BEAR_STANCE_ATTACKING) - stance = BEAR_STANCE_ALERT - stance_step = 6 - target_mob = M - ..() - -/mob/living/simple_animal/bear/Process_Spacemove(var/check_drift = 0) - return //No drifting in space for space bears! \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/carp.dm b/code/modules/mob/living/simple_animal/carp.dm deleted file mode 100644 index 1848eff5ad5..00000000000 --- a/code/modules/mob/living/simple_animal/carp.dm +++ /dev/null @@ -1,132 +0,0 @@ -#define CARP_STANCE_IDLE 1 -#define CARP_STANCE_ATTACK 2 -#define CARP_STANCE_ATTACKING 3 - -/mob/living/simple_animal/carp - name = "space carp" - desc = "A ferocious, fang-bearing creature that resembles a fish." - icon_state = "carp" - icon_living = "carp" - icon_dead = "carp_dead" - icon_gib = "carp_gib" - speak_chance = 0 - turns_per_move = 5 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - speed = -1 - stop_automated_movement_when_pulled = 0 - maxHealth = 25 - health = 25 - - harm_intent_damage = 8 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "bites" - attack_sound = 'sound/weapons/bite.ogg' - - //Space carp aren't affected by atmos. - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - - var/stance = CARP_STANCE_IDLE //Used to determine behavior - var/stance_step = 0 //Used to delay checks depending on what stance the bear is in - var/mob/living/target_mob //Once the bear enters attack stance, it will try to chase this mob. This it to prevent it changing it's mind between multiple mobs. - -/mob/living/simple_animal/carp/Life() - if(stat == DEAD) - walk(src,0)//STOP FUCKING MOVING GODDAMN - if(health > 0) - icon_state = icon_living - dead_mob_list -= src - living_mob_list += src - stat = CONSCIOUS - density = 1 - return - - - if(health < 1) - Die() - - if(health > maxHealth) - health = maxHealth - - if(!ckey && !stop_automated_movement) - if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. - turns_since_move++ - if(turns_since_move >= turns_per_move) - if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled - Move(get_step(src,pick(cardinal))) - turns_since_move = 0 - - if(!stat) - switch(stance) - if(CARP_STANCE_IDLE) - stop_automated_movement = 0 - stance_step++ - if(stance_step > 5) - stance_step = 0 - for(var/atom/A in view(7,src)) - if(iscarp(A)) - continue - - if(isliving(A)) - var/mob/living/L = A - if(!L.stat) - stance = CARP_STANCE_ATTACK - target_mob = L - break - - if(istype(A, /obj/mecha)) - var/obj/mecha/M = A - if (M.occupant) - stance = CARP_STANCE_ATTACK - target_mob = M - break - if (target_mob) - emote("nashes at [target_mob]") - - if(CARP_STANCE_ATTACK) //This one should only be active for one tick - stop_automated_movement = 1 - if(!target_mob || SA_attackable(target_mob)) - stance = CARP_STANCE_IDLE - stance_step = 5 //Make it very alert, so it quickly attacks again if a mob returns - if(target_mob in view(7,src)) - walk_to(src, target_mob, 1, 3) - stance = CARP_STANCE_ATTACKING - stance_step = 0 - - if(CARP_STANCE_ATTACKING) - stop_automated_movement = 1 - stance_step++ - if(!target_mob || SA_attackable(target_mob)) - stance = CARP_STANCE_IDLE - stance_step = 3 //Make it very alert, so it quickly attacks again if a mob returns - target_mob = null - return - if(!(target_mob in view(7,src))) - stance = CARP_STANCE_IDLE - stance_step = 1 - target_mob = null - return - if(get_dist(src, target_mob) <= 1) //Attacking - if(isliving(target_mob)) - var/mob/living/L = target_mob - L.attack_animal(src) - if(prob(10)) - L.Weaken(5) - L.visible_message("\the [src] knocks down \the [L]!") - if(istype(target_mob,/obj/mecha)) - var/obj/mecha/M = target_mob - M.attack_animal(src) - -/mob/living/simple_animal/carp/Process_Spacemove(var/check_drift = 0) - return //No drifting in space for space carp! //original comments do not steal \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm similarity index 100% rename from code/modules/mob/living/simple_animal/cat.dm rename to code/modules/mob/living/simple_animal/friendly/cat.dm diff --git a/code/modules/mob/living/simple_animal/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm similarity index 93% rename from code/modules/mob/living/simple_animal/corgi.dm rename to code/modules/mob/living/simple_animal/friendly/corgi.dm index 63405a57d02..242951d3299 100644 --- a/code/modules/mob/living/simple_animal/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -363,6 +363,28 @@ else ..() +/mob/living/simple_animal/corgi/regenerate_icons() + overlays = list() + + if(inventory_head) + var/head_icon_state = inventory_head.icon_state + if(health <= 0) + head_icon_state += "2" + + var/icon/head_icon = icon('icons/mob/corgi_head.dmi',head_icon_state) + if(head_icon) + overlays += head_icon + + if(inventory_back) + var/back_icon_state = inventory_back.icon_state + if(health <= 0) + back_icon_state += "2" + + var/icon/back_icon = icon('icons/mob/corgi_back.dmi',back_icon_state) + if(back_icon) + overlays += back_icon + return + /mob/living/simple_animal/corgi/puppy diff --git a/code/modules/mob/living/simple_animal/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm similarity index 100% rename from code/modules/mob/living/simple_animal/crab.dm rename to code/modules/mob/living/simple_animal/friendly/crab.dm diff --git a/code/modules/mob/living/simple_animal/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm similarity index 100% rename from code/modules/mob/living/simple_animal/mouse.dm rename to code/modules/mob/living/simple_animal/friendly/mouse.dm diff --git a/code/modules/mob/living/simple_animal/mushroom.dm b/code/modules/mob/living/simple_animal/friendly/mushroom.dm similarity index 100% rename from code/modules/mob/living/simple_animal/mushroom.dm rename to code/modules/mob/living/simple_animal/friendly/mushroom.dm diff --git a/code/modules/mob/living/simple_animal/tomato.dm b/code/modules/mob/living/simple_animal/friendly/tomato.dm similarity index 100% rename from code/modules/mob/living/simple_animal/tomato.dm rename to code/modules/mob/living/simple_animal/friendly/tomato.dm diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm new file mode 100644 index 00000000000..e3f44cdc2c2 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -0,0 +1,167 @@ +//Space bears! +/mob/living/simple_animal/hostile/bear + name = "space bear" + desc = "RawrRawr!!" + icon_state = "bear" + icon_living = "bear" + icon_dead = "bear_dead" + icon_gib = "bear_gib" + speak = list("RAWR!","Rawr!","GRR!","Growl!") + speak_emote = list("growls", "roars") + emote_hear = list("rawrs","grumbles","grawls") + emote_see = list("stares ferociously", "stomps") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "pokes the" + stop_automated_movement_when_pulled = 0 + maxHealth = 60 + health = 60 + melee_damage_lower = 20 + melee_damage_upper = 30 + + //Space bears aren't affected by atmos. + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + +//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! +/mob/living/simple_animal/hostile/bear/Hudson + name = "Hudson" + desc = "" + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "pokes" + +/mob/living/simple_animal/hostile/bear/Life() + . =..() + if(!.) + return + + if(loc && istype(loc,/turf/space)) + icon_state = "bear" + else + icon_state = "bearfloor" + + switch(stance) + + if(HOSTILE_STANCE_TIRED) + stop_automated_movement = 1 + stance_step++ + if(stance_step >= 10) //rests for 10 ticks + if(target_mob && target_mob in ListTargets()) + stance = HOSTILE_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle. + else + stance = HOSTILE_STANCE_IDLE + + if(HOSTILE_STANCE_ALERT) + stop_automated_movement = 1 + var/found_mob = 0 + if(target_mob && target_mob in ListTargets()) + if(!(SA_attackable(target_mob))) + stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again. + stance_step++ + found_mob = 1 + src.dir = get_dir(src,target_mob) //Keep staring at the mob + + if(stance_step in list(1,4,7)) //every 3 ticks + var/action = pick( list( "growls at [target_mob]", "stares angrily at [target_mob]", "prepares to attack [target_mob]", "closely watches [target_mob]" ) ) + if(action) + emote(action) + if(!found_mob) + stance_step-- + + if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode + stance = HOSTILE_STANCE_IDLE + if(stance_step >= 7) //If we have been staring at a mob for 7 ticks, + stance = HOSTILE_STANCE_ATTACK + + if(HOSTILE_STANCE_ATTACKING) + if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest + emote( "is worn out and needs to rest" ) + stance = HOSTILE_STANCE_TIRED + stance_step = 0 + walk(src, 0) //This stops the bear's walking + return + + + +/mob/living/simple_animal/hostile/bear/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) + stance = HOSTILE_STANCE_ALERT + stance_step = 6 + target_mob = user + ..() + +/mob/living/simple_animal/hostile/bear/attack_hand(mob/living/carbon/human/M as mob) + if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) + stance = HOSTILE_STANCE_ALERT + stance_step = 6 + target_mob = M + ..() + +/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/check_drift = 0) + return //No drifting in space for space bears! + +/mob/living/simple_animal/hostile/bear/FindTarget() + . = ..() + if(.) + emote("stares alertly at [.]") + stance = HOSTILE_STANCE_ALERT + +/mob/living/simple_animal/hostile/bear/LoseTarget() + ..(5) + +/mob/living/simple_animal/hostile/bear/AttackingTarget() + emote( pick( list("slashes at [target_mob]", "bites [target_mob]") ) ) + + var/damage = rand(20,30) + + if(ishuman(target_mob)) + var/mob/living/carbon/human/H = target_mob + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/datum/organ/external/affecting = H.get_organ(ran_zone(dam_zone)) + H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee")) + return H + else if(isliving(target_mob)) + var/mob/living/L = target_mob + L.adjustBruteLoss(damage) + return L + else if(istype(target_mob,/obj/mecha)) + var/obj/mecha/M = target_mob + M.attack_animal(src) + return M + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm new file mode 100644 index 00000000000..021cdbc241d --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -0,0 +1,52 @@ + + +/mob/living/simple_animal/hostile/carp + name = "space carp" + desc = "A ferocious, fang-bearing creature that resembles a fish." + icon_state = "carp" + icon_living = "carp" + icon_dead = "carp_dead" + icon_gib = "carp_gib" + speak_chance = 0 + turns_per_move = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speed = -1 + stop_automated_movement_when_pulled = 0 + maxHealth = 25 + health = 25 + + harm_intent_damage = 8 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "bites" + attack_sound = 'sound/weapons/bite.ogg' + + //Space carp aren't affected by atmos. + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + +/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/check_drift = 0) + return //No drifting in space for space carp! //original comments do not steal + +/mob/living/simple_animal/hostile/carp/FindTarget() + . = ..() + if(.) + emote("nashes at [.]") + +/mob/living/simple_animal/hostile/carp/AttackingTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(3) + L.visible_message("\the [src] knocks down \the [L]!") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm new file mode 100644 index 00000000000..011816156d5 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -0,0 +1,103 @@ +/mob/living/simple_animal/hostile + + var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior + var/stance_step = 0 //Used to delay checks depending on what stance the hostile + var/mob/living/target_mob //Once the bear enters attack stance, it will try to chase this mob. This it to prevent it changing it's mind between multiple mobs. + var/attack_same = 0 + +/mob/living/simple_animal/hostile/proc/FindTarget() + + var/atom/T = null + stop_automated_movement = 0 + stance_step++ + if(stance_step > 5) + stance_step = 0 + for(var/atom/A in ListTargets()) + + if(!attack_same && istype(A, src.type)) + continue + + if(isliving(A)) + var/mob/living/L = A + if(!L.stat) + stance = HOSTILE_STANCE_ATTACK + T = L + break + if(istype(A, /obj/mecha)) + var/obj/mecha/M = A + if (M.occupant) + stance = HOSTILE_STANCE_ATTACK + T = M + break + return T + +/mob/living/simple_animal/hostile/proc/MoveToTarget(var/step = 5) + stop_automated_movement = 1 + if(!target_mob || SA_attackable(target_mob)) + stance = HOSTILE_STANCE_IDLE + stance_step = step //Make it very alert, so it quickly attacks again if a mob returns + if(target_mob in ListTargets()) + walk_to(src, target_mob, 1, 3) + stance = HOSTILE_STANCE_ATTACKING + stance_step = 0 + +/mob/living/simple_animal/hostile/proc/AttackTarget() + + stop_automated_movement = 1 + stance_step++ + if(!target_mob || SA_attackable(target_mob)) + LoseTarget() + return + if(!(target_mob in ListTargets())) + LostTarget() + return + if(get_dist(src, target_mob) <= 1) //Attacking + AttackingTarget() + +/mob/living/simple_animal/hostile/proc/AttackingTarget() + if(isliving(target_mob)) + var/mob/living/L = target_mob + L.attack_animal(src) + return L + if(istype(target_mob,/obj/mecha)) + var/obj/mecha/M = target_mob + M.attack_animal(src) + return M + +/mob/living/simple_animal/hostile/proc/LoseTarget(var/step = 3) + stance = HOSTILE_STANCE_IDLE + stance_step = step + target_mob = null + walk(src, 0) + +/mob/living/simple_animal/hostile/proc/LostTarget(var/step = 1) + stance = HOSTILE_STANCE_IDLE + stance_step = step + walk(src, 0) + + +/mob/living/simple_animal/hostile/proc/ListTargets() + return view(src, 7) + +/mob/living/simple_animal/hostile/Die() + ..() + walk(src, 0) + +/mob/living/simple_animal/hostile/Life() + + . = ..() + if(!.) + walk(src, 0) + return 0 + if(client) + return 0 + if(!stat) + switch(stance) + if(HOSTILE_STANCE_IDLE) + target_mob = FindTarget() + + if(HOSTILE_STANCE_ATTACK) //This one should only be active for one tick + MoveToTarget() + + if(HOSTILE_STANCE_ATTACKING) + AttackTarget() diff --git a/code/modules/mob/living/simple_animal/life.dm b/code/modules/mob/living/simple_animal/life.dm deleted file mode 100644 index 87e4601d718..00000000000 --- a/code/modules/mob/living/simple_animal/life.dm +++ /dev/null @@ -1,431 +0,0 @@ -/mob/living/simple_animal - name = "animal" - icon = 'icons/mob/animal.dmi' - health = 20 - maxHealth = 20 - - var/icon_living = "" - var/icon_dead = "" - var/icon_gib = null //We only try to show a gibbing animation if this exists. - - var/list/speak = list() - var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. - var/speak_chance = 0 - var/list/emote_hear = list() //Hearable emotes - var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps - - var/turns_per_move = 1 - var/turns_since_move = 0 - universal_speak = 1 - var/meat_amount = 0 - var/meat_type - var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. - var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. - - //Interaction - var/response_help = "You try to help" - var/response_disarm = "You try to disarm" - var/response_harm = "You try to hurt" - var/harm_intent_damage = 3 - - //Temperature effect - var/minbodytemp = 250 - var/maxbodytemp = 350 - var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp - var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp - - //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage - var/min_oxy = 5 - var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum - var/min_tox = 0 - var/max_tox = 1 - var/min_co2 = 0 - var/max_co2 = 5 - var/min_n2 = 0 - var/max_n2 = 0 - var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above - - - //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly - var/melee_damage_lower = 0 - var/melee_damage_upper = 0 - var/attacktext = "attacks" - var/attack_sound = null - var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/wall_smash = 0 //if they can smash walls - - var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster - -/mob/living/simple_animal/New() - ..() - verbs -= /mob/verb/observe - -/mob/living/simple_animal/Login() - if(src && src.client) - src.client.screen = null - ..() - -/mob/living/simple_animal/Life() - - //Health - if(stat == DEAD) - if(health > 0) - icon_state = icon_living - dead_mob_list -= src - living_mob_list += src - stat = CONSCIOUS - density = 1 - return - - - if(health < 1) - Die() - - if(health > maxHealth) - health = maxHealth - - if(stunned) - AdjustStunned(-1) - if(weakened) - AdjustWeakened(-1) - if(paralysis) - AdjustParalysis(-1) - - //Movement - if(!client && !stop_automated_movement) - if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. - turns_since_move++ - if(turns_since_move >= turns_per_move) - if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled - Move(get_step(src,pick(cardinal))) - turns_since_move = 0 - - //Speaking - if(!client && speak_chance) - if(rand(0,200) < speak_chance) - if(speak && speak.len) - if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) - var/length = speak.len - if(emote_hear && emote_hear.len) - length += emote_hear.len - if(emote_see && emote_see.len) - length += emote_see.len - var/randomValue = rand(1,length) - if(randomValue <= speak.len) - say(pick(speak)) - else - randomValue -= speak.len - if(emote_see && randomValue <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - else - say(pick(speak)) - else - if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - emote(pick(emote_see),1) - if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len)) - emote(pick(emote_hear),2) - if((emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - var/length = emote_hear.len + emote_see.len - var/pick = rand(1,length) - if(pick <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - - - //Atmos - var/atmos_suitable = 1 - - var/atom/A = src.loc - if(isturf(A)) - var/turf/T = A - var/areatemp = T.temperature - if( abs(areatemp - bodytemperature) > 40 ) - var/diff = areatemp - bodytemperature - diff = diff / 5 - //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]" - bodytemperature += diff - - if(istype(T,/turf/simulated)) - var/turf/simulated/ST = T - if(ST.air) - var/tox = ST.air.toxins - var/oxy = ST.air.oxygen - var/n2 = ST.air.nitrogen - var/co2 = ST.air.carbon_dioxide - - if(min_oxy) - if(oxy < min_oxy) - atmos_suitable = 0 - if(max_oxy) - if(oxy > max_oxy) - atmos_suitable = 0 - if(min_tox) - if(tox < min_tox) - atmos_suitable = 0 - if(max_tox) - if(tox > max_tox) - atmos_suitable = 0 - if(min_n2) - if(n2 < min_n2) - atmos_suitable = 0 - if(max_n2) - if(n2 > max_n2) - atmos_suitable = 0 - if(min_co2) - if(co2 < min_co2) - atmos_suitable = 0 - if(max_co2) - if(co2 > max_co2) - atmos_suitable = 0 - - //Atmos effect - if(bodytemperature < minbodytemp) - health -= cold_damage_per_tick - else if(bodytemperature > maxbodytemp) - health -= heat_damage_per_tick - - if(!atmos_suitable) - health -= unsuitable_atoms_damage - -/mob/living/simple_animal/Bumped(AM as mob|obj) - if(!AM) return - - if(resting || buckled) - return - - if(isturf(src.loc)) - if(ismob(AM)) - var/newamloc = src.loc - src.loc = AM:loc - AM:loc = newamloc - else - ..() - -/mob/living/simple_animal/gib() - if(icon_gib) - flick(icon_gib, src) - if(meat_amount && meat_type) - for(var/i = 0; i < meat_amount; i++) - new meat_type(src.loc) - ..() - -/mob/living/simple_animal/say_quote(var/text) - if(speak_emote && speak_emote.len) - var/emote = pick(speak_emote) - if(emote) - return "[emote], \"[text]\"" - return "says, \"[text]\""; - -/mob/living/simple_animal/emote(var/act) - if(act) - if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P - for (var/mob/O in viewers(src, null)) - O.show_message("[src] [act].") - - -/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) - M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - health -= damage - -/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) - if(!Proj) return - src.health -= Proj.damage - return 0 - -/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob) - ..() - - switch(M.a_intent) - - if("help") - if (health > 0) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\blue [M] [response_help] [src]") - - if("grab") - if (M == src) - return - if (nopush) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if("hurt") - health -= harm_intent_damage - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] [response_harm] [src]") - - if("disarm") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\blue [M] [response_disarm] [src]") - - return - -/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - - switch(M.a_intent) - - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - if ("grab") - if(M == src) - return - if (nopush) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if("hurt") - var/damage = rand(15, 30) - visible_message("\red [M] has slashed at [src]!") - src.health -= damage - - - if("disarm") - var/damage = rand(15, 30) - visible_message("\red [M] has slashed at [src]!") - src.health -= damage - - return - -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L as mob) - - switch(L.a_intent) - if("help") - visible_message("\blue [L] rubs it's head against [src]") - - else - - var/damage = rand(5, 10) - visible_message("\red [L] bites [src]!") - - if(stat != DEAD) - src.health -= damage - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - - -/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri - if(istype(O, /obj/item/stack/medical)) - if(stat != DEAD) - var/obj/item/stack/medical/MED = O - if(health < maxHealth) - if(MED.amount >= 1) - health = min(maxHealth, health + MED.heal_brute) - MED.amount -= 1 - if(MED.amount <= 0) - del(MED) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] applies the [MED] on [src]") - else - user << "\blue this [src] is dead, medical items won't bring it back to life." - if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. - if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch)) - new meat_type (get_turf(src)) - if(prob(95)) - del(src) - return - gib() - else - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - health -= damage - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") - else - usr << "\red This weapon is ineffective, it does no damage." - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with the [O]. ") - - -/mob/living/simple_animal/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = speed - - return tally+config.animal_delay - -/mob/living/simple_animal/Stat() - ..() - - statpanel("Status") - stat(null, "Health: [round((health / maxHealth) * 100)]%") - -/mob/living/simple_animal/proc/Die() - living_mob_list -= src - dead_mob_list += src - icon_state = icon_dead - stat = DEAD - density = 0 - return - -/mob/living/simple_animal/ex_act(severity) - if(!blinded) - flick("flash", flash) - switch (severity) - if (1.0) - health -= 500 - gib() - return - - if (2.0) - health -= 60 - - - if(3.0) - health -= 30 - -/mob/living/simple_animal/adjustBruteLoss(damage) - health -= damage - -/mob/living/simple_animal/proc/SA_attackable(target_mob) - if (isliving(target_mob)) - var/mob/living/L = target_mob - if(!L.stat) - return (0) - if (istype(target_mob,/obj/mecha)) - var/obj/mecha/M = target_mob - if (M.occupant) - return (0) - return (1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 4e2759e806d..b2f2f33287f 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -1,2 +1,435 @@ +/mob/living/simple_animal + name = "animal" + icon = 'icons/mob/animal.dmi' + health = 20 + maxHealth = 20 + + var/icon_living = "" + var/icon_dead = "" + var/icon_gib = null //We only try to show a gibbing animation if this exists. + + var/list/speak = list() + var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. + var/speak_chance = 0 + var/list/emote_hear = list() //Hearable emotes + var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps + + var/turns_per_move = 1 + var/turns_since_move = 0 + universal_speak = 1 + var/meat_amount = 0 + var/meat_type + var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. + var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. + + //Interaction + var/response_help = "You try to help" + var/response_disarm = "You try to disarm" + var/response_harm = "You try to hurt" + var/harm_intent_damage = 3 + + //Temperature effect + var/minbodytemp = 250 + var/maxbodytemp = 350 + var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp + var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp + + //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage + var/min_oxy = 5 + var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum + var/min_tox = 0 + var/max_tox = 1 + var/min_co2 = 0 + var/max_co2 = 5 + var/min_n2 = 0 + var/max_n2 = 0 + var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above + + + //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly + var/melee_damage_lower = 0 + var/melee_damage_upper = 0 + var/attacktext = "attacks" + var/attack_sound = null + var/friendly = "nuzzles" //If the mob does no damage with it's attack + var/wall_smash = 0 //if they can smash walls + + var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster + +/mob/living/simple_animal/New() + ..() + verbs -= /mob/verb/observe + +/mob/living/simple_animal/Login() + if(src && src.client) + src.client.screen = null + ..() + /mob/living/simple_animal/updatehealth() - return \ No newline at end of file + return + +/mob/living/simple_animal/Life() + + //Health + if(stat == DEAD) + if(health > 0) + icon_state = icon_living + dead_mob_list -= src + living_mob_list += src + stat = CONSCIOUS + density = 1 + return 0 + + + if(health < 1) + Die() + + if(health > maxHealth) + health = maxHealth + + if(stunned) + AdjustStunned(-1) + if(weakened) + AdjustWeakened(-1) + if(paralysis) + AdjustParalysis(-1) + + //Movement + if(!client && !stop_automated_movement) + if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. + turns_since_move++ + if(turns_since_move >= turns_per_move) + if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled + Move(get_step(src,pick(cardinal))) + turns_since_move = 0 + + //Speaking + if(!client && speak_chance) + if(rand(0,200) < speak_chance) + if(speak && speak.len) + if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) + var/length = speak.len + if(emote_hear && emote_hear.len) + length += emote_hear.len + if(emote_see && emote_see.len) + length += emote_see.len + var/randomValue = rand(1,length) + if(randomValue <= speak.len) + say(pick(speak)) + else + randomValue -= speak.len + if(emote_see && randomValue <= emote_see.len) + emote(pick(emote_see),1) + else + emote(pick(emote_hear),2) + else + say(pick(speak)) + else + if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len)) + emote(pick(emote_see),1) + if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len)) + emote(pick(emote_hear),2) + if((emote_hear && emote_hear.len) && (emote_see && emote_see.len)) + var/length = emote_hear.len + emote_see.len + var/pick = rand(1,length) + if(pick <= emote_see.len) + emote(pick(emote_see),1) + else + emote(pick(emote_hear),2) + + + //Atmos + var/atmos_suitable = 1 + + var/atom/A = src.loc + if(isturf(A)) + var/turf/T = A + var/areatemp = T.temperature + if( abs(areatemp - bodytemperature) > 40 ) + var/diff = areatemp - bodytemperature + diff = diff / 5 + //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]" + bodytemperature += diff + + if(istype(T,/turf/simulated)) + var/turf/simulated/ST = T + if(ST.air) + var/tox = ST.air.toxins + var/oxy = ST.air.oxygen + var/n2 = ST.air.nitrogen + var/co2 = ST.air.carbon_dioxide + + if(min_oxy) + if(oxy < min_oxy) + atmos_suitable = 0 + if(max_oxy) + if(oxy > max_oxy) + atmos_suitable = 0 + if(min_tox) + if(tox < min_tox) + atmos_suitable = 0 + if(max_tox) + if(tox > max_tox) + atmos_suitable = 0 + if(min_n2) + if(n2 < min_n2) + atmos_suitable = 0 + if(max_n2) + if(n2 > max_n2) + atmos_suitable = 0 + if(min_co2) + if(co2 < min_co2) + atmos_suitable = 0 + if(max_co2) + if(co2 > max_co2) + atmos_suitable = 0 + + //Atmos effect + if(bodytemperature < minbodytemp) + health -= cold_damage_per_tick + else if(bodytemperature > maxbodytemp) + health -= heat_damage_per_tick + + if(!atmos_suitable) + health -= unsuitable_atoms_damage + return 1 + +/mob/living/simple_animal/Bumped(AM as mob|obj) + if(!AM) return + + if(resting || buckled) + return + + if(isturf(src.loc)) + if(ismob(AM)) + var/newamloc = src.loc + src.loc = AM:loc + AM:loc = newamloc + else + ..() + +/mob/living/simple_animal/gib() + if(icon_gib) + flick(icon_gib, src) + if(meat_amount && meat_type) + for(var/i = 0; i < meat_amount; i++) + new meat_type(src.loc) + ..() + +/mob/living/simple_animal/say_quote(var/text) + if(speak_emote && speak_emote.len) + var/emote = pick(speak_emote) + if(emote) + return "[emote], \"[text]\"" + return "says, \"[text]\""; + +/mob/living/simple_animal/emote(var/act) + if(act) + if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P + for (var/mob/O in viewers(src, null)) + O.show_message("[src] [act].") + + +/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) + if(M.melee_damage_upper == 0) + M.emote("[M.friendly] [src]") + else + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + for(var/mob/O in viewers(src, null)) + O.show_message("\red [M] [M.attacktext] [src]!", 1) + M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + health -= damage + +/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) + if(!Proj) return + src.health -= Proj.damage + return 0 + +/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob) + ..() + + switch(M.a_intent) + + if("help") + if (health > 0) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\blue [M] [response_help] [src]") + + if("grab") + if (M == src) + return + if (nopush) + return + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + + LAssailant = M + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + if("hurt") + health -= harm_intent_damage + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] [response_harm] [src]") + + if("disarm") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\blue [M] [response_disarm] [src]") + + return + +/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + + switch(M.a_intent) + + if ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + if ("grab") + if(M == src) + return + if (nopush) + return + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + if("hurt") + var/damage = rand(15, 30) + visible_message("\red [M] has slashed at [src]!") + src.health -= damage + + + if("disarm") + var/damage = rand(15, 30) + visible_message("\red [M] has slashed at [src]!") + src.health -= damage + + return + +/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L as mob) + + switch(L.a_intent) + if("help") + visible_message("\blue [L] rubs it's head against [src]") + + else + + var/damage = rand(5, 10) + visible_message("\red [L] bites [src]!") + + if(stat != DEAD) + src.health -= damage + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + + +/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri + if(istype(O, /obj/item/stack/medical)) + if(stat != DEAD) + var/obj/item/stack/medical/MED = O + if(health < maxHealth) + if(MED.amount >= 1) + health = min(maxHealth, health + MED.heal_brute) + MED.amount -= 1 + if(MED.amount <= 0) + del(MED) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\blue [user] applies the [MED] on [src]") + else + user << "\blue this [src] is dead, medical items won't bring it back to life." + if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. + if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch)) + new meat_type (get_turf(src)) + if(prob(95)) + del(src) + return + gib() + else + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + health -= damage + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") + else + usr << "\red This weapon is ineffective, it does no damage." + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with the [O]. ") + + +/mob/living/simple_animal/movement_delay() + var/tally = 0 //Incase I need to add stuff other than "speed" later + + tally = speed + + return tally+config.animal_delay + +/mob/living/simple_animal/Stat() + ..() + + statpanel("Status") + stat(null, "Health: [round((health / maxHealth) * 100)]%") + +/mob/living/simple_animal/proc/Die() + living_mob_list -= src + dead_mob_list += src + icon_state = icon_dead + stat = DEAD + density = 0 + return + +/mob/living/simple_animal/ex_act(severity) + if(!blinded) + flick("flash", flash) + switch (severity) + if (1.0) + health -= 500 + gib() + return + + if (2.0) + health -= 60 + + + if(3.0) + health -= 30 + +/mob/living/simple_animal/adjustBruteLoss(damage) + health -= damage + +/mob/living/simple_animal/proc/SA_attackable(target_mob) + if (isliving(target_mob)) + var/mob/living/L = target_mob + if(!L.stat) + return (0) + if (istype(target_mob,/obj/mecha)) + var/obj/mecha/M = target_mob + if (M.occupant) + return (0) + return (1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/update_icons.dm b/code/modules/mob/living/simple_animal/update_icons.dm deleted file mode 100644 index be27f91f01c..00000000000 --- a/code/modules/mob/living/simple_animal/update_icons.dm +++ /dev/null @@ -1,21 +0,0 @@ -/mob/living/simple_animal/corgi/regenerate_icons() - overlays = list() - - if(inventory_head) - var/head_icon_state = inventory_head.icon_state - if(health <= 0) - head_icon_state += "2" - - var/icon/head_icon = icon('icons/mob/corgi_head.dmi',head_icon_state) - if(head_icon) - overlays += head_icon - - if(inventory_back) - var/back_icon_state = inventory_back.icon_state - if(health <= 0) - back_icon_state += "2" - - var/icon/back_icon = icon('icons/mob/corgi_back.dmi',back_icon_state) - if(back_icon) - overlays += back_icon - return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 2a0310752c6..882579164f0 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -66,12 +66,12 @@ return 0 /proc/isbear(A) - if(istype(A, /mob/living/simple_animal/bear)) + if(istype(A, /mob/living/simple_animal/hostile/bear)) return 1 return 0 /proc/iscarp(A) - if(istype(A, /mob/living/simple_animal/carp)) + if(istype(A, /mob/living/simple_animal/hostile/carp)) return 1 return 0 diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index eaf115c3dd3..d70d6653bfc 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -357,7 +357,7 @@ return 1 if(ispath(MP, /mob/living/simple_animal/crab)) return 1 - if(ispath(MP, /mob/living/simple_animal/carp)) + if(ispath(MP, /mob/living/simple_animal/hostile/carp)) return 1 if(ispath(MP, /mob/living/simple_animal/mushroom)) return 1 @@ -367,7 +367,7 @@ return 1 if(ispath(MP, /mob/living/simple_animal/mouse)) return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak) - if(ispath(MP, /mob/living/simple_animal/bear)) + if(ispath(MP, /mob/living/simple_animal/hostile/bear)) return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak) if(ispath(MP, /mob/living/simple_animal/parrot)) return 1 //Parrots are no longer unfinished! -Nodrak diff --git a/code/setup.dm b/code/setup.dm index 32f371fe596..db6d6b54b34 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -523,4 +523,10 @@ var/list/TAGGERLOCATIONS = list("Disposals", "Atmospherics", "Security", "HoS Office", "Medbay", "CMO Office", "Chemistry", "Research", "RD Office", "Robotics", "HoP Office", "Library", "Chapel", "Theatre", - "Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics") \ No newline at end of file + "Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics") + +#define HOSTILE_STANCE_IDLE 1 +#define HOSTILE_STANCE_ALERT 2 +#define HOSTILE_STANCE_ATTACK 3 +#define HOSTILE_STANCE_ATTACKING 4 +#define HOSTILE_STANCE_TIRED 5 \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index c6b2d5788ee..de3f7b6e350 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -399,6 +399,8 @@ #define FILE_DIR "code/modules/mob/living/silicon/pai" #define FILE_DIR "code/modules/mob/living/silicon/robot" #define FILE_DIR "code/modules/mob/living/simple_animal" +#define FILE_DIR "code/modules/mob/living/simple_animal/friendly" +#define FILE_DIR "code/modules/mob/living/simple_animal/hostile" #define FILE_DIR "code/modules/mob/new_player" #define FILE_DIR "code/modules/paperwork" #define FILE_DIR "code/modules/power" @@ -1370,23 +1372,22 @@ #include "code\modules\mob\living\silicon\robot\robot_movement.dm" #include "code\modules\mob\living\silicon\robot\say.dm" #include "code\modules\mob\living\silicon\robot\wires.dm" -#include "code\modules\mob\living\simple_animal\bear.dm" -#include "code\modules\mob\living\simple_animal\carp.dm" -#include "code\modules\mob\living\simple_animal\cat.dm" #include "code\modules\mob\living\simple_animal\clown.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" -#include "code\modules\mob\living\simple_animal\corgi.dm" -#include "code\modules\mob\living\simple_animal\crab.dm" -#include "code\modules\mob\living\simple_animal\life.dm" -#include "code\modules\mob\living\simple_animal\mouse.dm" -#include "code\modules\mob\living\simple_animal\mushroom.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" #include "code\modules\mob\living\simple_animal\shade.dm" #include "code\modules\mob\living\simple_animal\simple_animal.dm" #include "code\modules\mob\living\simple_animal\syndicate.dm" -#include "code\modules\mob\living\simple_animal\tomato.dm" -#include "code\modules\mob\living\simple_animal\update_icons.dm" #include "code\modules\mob\living\simple_animal\worm.dm" +#include "code\modules\mob\living\simple_animal\friendly\cat.dm" +#include "code\modules\mob\living\simple_animal\friendly\corgi.dm" +#include "code\modules\mob\living\simple_animal\friendly\crab.dm" +#include "code\modules\mob\living\simple_animal\friendly\mouse.dm" +#include "code\modules\mob\living\simple_animal\friendly\mushroom.dm" +#include "code\modules\mob\living\simple_animal\friendly\tomato.dm" +#include "code\modules\mob\living\simple_animal\hostile\bear.dm" +#include "code\modules\mob\living\simple_animal\hostile\carp.dm" +#include "code\modules\mob\living\simple_animal\hostile\hostile.dm" #include "code\modules\mob\new_player\hud.dm" #include "code\modules\mob\new_player\login.dm" #include "code\modules\mob\new_player\logout.dm"