From 01ff6eeb8ef74dfbc421bef2f064e1c639b627e6 Mon Sep 17 00:00:00 2001 From: Werner Date: Sat, 10 Oct 2020 21:06:56 +0200 Subject: [PATCH] Adds a mob for the beach event. --- aurorastation.dme | 1 + .../mob/living/simple_animal/hostile/shark.dm | 216 ++++++++++++++++++ icons/mob/npc/shark.dmi | Bin 0 -> 2929 bytes 3 files changed, 217 insertions(+) create mode 100644 code/modules/mob/living/simple_animal/hostile/shark.dm create mode 100644 icons/mob/npc/shark.dmi diff --git a/aurorastation.dme b/aurorastation.dme index 042fdaff08c..afdac353c2b 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -2121,6 +2121,7 @@ #include "code\modules\mob\living\simple_animal\hostile\pra.dm" #include "code\modules\mob\living\simple_animal\hostile\russian.dm" #include "code\modules\mob\living\simple_animal\hostile\sarlacc.dm" +#include "code\modules\mob\living\simple_animal\hostile\shark.dm" #include "code\modules\mob\living\simple_animal\hostile\spider_queen.dm" #include "code\modules\mob\living\simple_animal\hostile\syndicate.dm" #include "code\modules\mob\living\simple_animal\hostile\tree.dm" diff --git a/code/modules/mob/living/simple_animal/hostile/shark.dm b/code/modules/mob/living/simple_animal/hostile/shark.dm new file mode 100644 index 00000000000..ca8bbf53588 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/shark.dm @@ -0,0 +1,216 @@ + + +/mob/living/simple_animal/eventshark + name = "shark" + desc = "A ferocious, fang-bearing creature." + icon = 'icons/mob/npc/shark.dmi' + icon_state = "shark" + icon_living = "shark" + icon_dead = "shark_dead" + icon_rest = "shark_rest" + icon_gib = "carp_gib" + speak_chance = 0 + turns_per_move = 5 + meat_type = /obj/item/reagent_containers/food/snacks/fish/carpmeat + organ_names = list("head", "chest", "tail", "left flipper", "right flipper") + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speed = 1 + meat_amount = 5 + maxHealth = 700 + health = 700 + mob_size = 15 + see_in_dark = 10 + see_invisible = SEE_INVISIBLE_NOLIGHTING + + harm_intent_damage = 5 + melee_damage_lower = 25 + melee_damage_upper = 30 + resist_mod = 15 // LOL good luck pal + attacktext = "bitten" + attack_sound = 'sound/weapons/bite.ogg' + + mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY + mob_push_flags = ALLMOBS + + //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 + + faction = "carp" + + flying = TRUE + + var/diving = FALSE + var/mouth_open = TRUE + +/mob/living/simple_animal/eventshark/Allow_Spacemove(var/check_drift = 0) + return 1 //No drifting in space for space carp! //original comments do not steal + +/mob/living/simple_animal/eventshark/verb/dive() + set category = "Shark" + + if(!diving) + visible_message(SPAN_NOTICE("\The [src] dives down and vanishes from view.")) + invisibility = INVISIBILITY_MAXIMUM + speed = 0.5 + density = FALSE + else + invisibility = 0 + visible_message(SPAN_NOTICE("\The [src] emerges from the depths.")) + speed = 1 + density = TRUE + + diving = !diving + +/mob/living/simple_animal/eventshark/MiddleClickOn(var/atom/A) + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(!Adjacent(H)) + return + + if(!health) + return + + var/limblist = list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG) + while(length(limblist)) + var/limbname = pick(limblist) + limblist -= limbname + var/obj/item/organ/external/O = H.get_organ(limbname) + if(!O) + continue + if(O.is_stump()) + continue + O.droplimb(FALSE,DROPLIMB_BLUNT) + visible_message(SPAN_WARNING("\The [src] bites off [H]'s [O].")) + return + var/obj/item/organ/external/O = H.get_organ(BP_HEAD) + if(!O) + return + if(O.is_stump()) + return + O.droplimb(FALSE,DROPLIMB_EDGE) + visible_message(SPAN_WARNING("\The [src] bites off [H]'s [O].")) + + else if(istype(A,/obj/item)) + if(!Adjacent(A)) + return + + if(!health) + return + + visible_message(SPAN_WARNING("\The [src] devours \the [A]")) + qdel(A) + + return + return + +/** + * Attempt to devour victim + * + * Returns TRUE on success, FALSE on failure + +/mob/living/simple_animal/eventshark/proc/devour(atom/movable/victim) + + var/eat_speed = 100 + if(ismob(victim)) + eat_speed *= 3 //We want our bites to take a lot so as to not spam the chat. + do_gradual_devour(victim, eat_speed) + return + src.visible_message("\The [src] is attempting to devour \the [victim] whole!") + var/mob/target = victim + if(isobj(victim)) + target = src + if(!do_mob(src,target,eat_speed)) + return FALSE + src.visible_message("\The [src] devours \the [victim] whole!") + if(ismob(victim)) + admin_attack_log(src, victim, "Devoured.", "Was devoured by.", "devoured") + else + src.drop_from_inventory(victim) + move_to_stomach(victim) + + return TRUE + +/mob/living/simple_animal/eventshark/proc/move_to_stomach(atom/movable/victim) + return + +// Snowflake procs for unathi. Because lore said so. + +/mob/living/simple_animal/eventshark/proc/do_gradual_devour(var/mob/living/victim, var/eat_speed) + set waitfor = FALSE + + //This function will start consuming the victim by taking bites out of them. + //Victim or attacker moving will interrupt it + //A bite will be taken every 4 seconds + var/bite_delay = 4 + var/bite_size = mouth_size * 0.5 + var/num_bites_needed = (victim.mob_size * 2)/bite_size //Total bites needed to eat it from full health + var/PEPB = 1/num_bites_needed //Percentage eaten per bite + var/turf/ourloc = src.loc + var/turf/victimloc = victim.loc + var/messes = 0 //Number of bloodstains we've placed + var/datum/reagents/vessel = victim.get_vessel(1) + if(!victim.composition_reagent_quantity) + victim.calculate_composition() + var/dam_multiplier = 1 + + var/victim_maxhealth = victim.maxHealth //We cache this here in case we need to edit it. + + var/damage_dealt = victim_maxhealth * PEPB * dam_multiplier + + //Now, incase we're resuming an earlier feeding session on the same creature + //We calculate the actual bites needed to fully eat it based on how eaten it already is + if(victim.getBruteLoss()) + var/percentageDamaged = victim.getBruteLoss() / victim_maxhealth + var/percentageRemaining = 1 - percentageDamaged + num_bites_needed = percentageRemaining / PEPB + + var/time_needed_seconds = num_bites_needed*bite_delay//in seconds for now + var/time_needed_minutes + var/time_needed_string + if (time_needed_seconds > 60) + time_needed_minutes = round((time_needed_seconds/60)) + time_needed_seconds = time_needed_seconds % 60 + time_needed_string = "[time_needed_minutes] minutes and [time_needed_seconds] seconds" + else + time_needed_string = "[time_needed_seconds] seconds" + + src.visible_message("[src] starts to devour [victim]!", \ + "You start devouring [victim], this will take approximately [time_needed_string]. You and the victim must remain still to continue, \ + but you can interrupt feeding anytime and leave with what you've already eaten.") + + for (var/i = 0 to num_bites_needed) + if(do_mob(src, victim, bite_delay * 10, extra_checks = CALLBACK(src, .proc/devour_in_range, victim))) + face_atom(victim) + victim.apply_damage(damage_dealt, BRUTE) + var/obj/item/organ/internal/stomach/S = internal_organs_by_name[BP_STOMACH] + if(S) + S.ingested.add_reagent(victim.composition_reagent, (victim.composition_reagent_quantity * 0.5) * PEPB) + visible_message("[src] bites a chunk out of [victim]!","[bitemessage(victim)]") + if(messes < victim.mob_size - 1 && prob(50)) + handle_devour_mess(src, victim, vessel) + if(victim.getBruteLoss() >= victim_maxhealth) + visible_message("[src] finishes devouring [victim].","You finish devouring [victim].") + handle_devour_mess(src, victim, vessel, 1) + qdel(victim) + else + if(nutrition >= (max_nutrition - 60)) + to_chat(src, "Your stomach is full!") + if (victim && !QDELETED(victim) && victimloc != victim.loc) //This procs when the victim gets moved to nullspace. + to_chat(src, "[victim] moved away, you need to keep it still. Try grabbing, stunning or killing it first.") + else if (ourloc != src.loc) + to_chat(src, "You moved! Devouring cancelled.") + break + +/mob/living/simple_animal/eventshark/proc/devour_in_range(var/mob/victim) + return victim in range(2, src) + */ diff --git a/icons/mob/npc/shark.dmi b/icons/mob/npc/shark.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f9582583278a7fedc7688ed078bfdced1064953f GIT binary patch literal 2929 zcmV-%3y$=OP){p0000O@y3(@ z0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS z%+FJ>RWQ*r;NmRLOex6#ag4Y)Gg33tGfE(w;*!LYR3KBSI3uwrTZxM^C9|j)B*n#< zR+N~V3T3CH<|I}EnWj2mh^8$*B{eYxq1Odvq+tY000VL zNklHHQuESQU^dYoRs#I+2UD!ohVKNID ziRbfaiOdX5_7BUX4`XWkxXUK#`7{G^|I(*CzwTy8o>e58bi36fB!x_qC0di|u}HsQ zj(pg8`el)l$+D-4@=kjG(gUx{{L-Nd)r0>FMVbUzDgu#mNT!tHZkjF9YQG#2EIK_) zVUEH)nWK(Jc^-En^0-saZR>A^=bZ`r%v+-smz^c@y!z~i zSxCQan14MQNHnP}%RC$sq~htA6&Dk&>vlJpJ4qj?F=1(!`#rAnu7@6dHq)iBdXx-E z3xcGlZCSUkh{zzV@%z&1kT$01#B%mEvcBh`P*bKJ`6?1ox*iYuT?-S+{>ROW~>rM^w}>VR&QmgZ z8+XrEeUAQ-z%P%7{no0M2#GFTVEFwcL1nqpQyWSZh^#RBa;L{%kj6kL80Tc^nTNf; zhE;}fS(ora%w&$(wZA8|*Yv|#ReA{wg8kO~GO;A(+XKlVb091}j}*U+FYqf#{7_t? z7vf4?DuPrma(LRws!~Qsll!66<1QXz*%AVvS48?Scv-pA5=H)62v;aY>XGWon8;r~ zE2#Z#I8sbgT1VxVzqruiU7)V4{N5E6LdiwBRxQ&W58cI@km1N0I?HP zgh2x}GuRir5HWj;0dO}$m; z3>w%Z#jXoy!l)JMl)-+{LJE79sFfqOz@0Q`AdZvVbx|LCP;S#yN3v3Tb(a)Fx&hD` zgT{oJXk_8Ks1@ozU>CuDQHQrucV*PdVOQ;Z-k>p;TmPs*125En#ICOZuBTfQ9*}0t z%;1r*V%_K19R`hJ>mPGnV1))E%_O$v-+~9E3X?{{s_Zjp%;obAcU|B}Dni=sR1`^V zlQg3S4ew@PFldxWnCqfeC+w(76__gP&PoAkMhzMhpFtzPI_kPWk=*8-LsG&&Oi?8N zlyN>T)Sxj*E`tW*W+1vQY{n%K(3&1j+d?DkcFd4Qu|V z8Z;szgH+uo+@ui_X3&_p3>wHtQC%0_m|*=_ZKTzK!rJT;j&%mrj!I_-A}Mz3M~kE;4O#5w6ClpaS_onQKyNbY$7olH1<;QS}}eE5+_pw ziHV4qi;t;}#70C+#>P~$Hc-tGv>;_eeit~cOiw#-&S#Qcam5u^{6FJU9W*)|FK4|m zKcRyLO-Ub;k95#rL85vrKGQ*i2Z`<``alPbojxa7ij&@$&vek(>vNK(IO&b~SO*RA zvN`XK`9KGaX}>8*oc6RgW_$+?E+n!yW^@OQiPYz0Q!;pC26xbyXnjsLC4)C+YzK|f zMpFmk^2Utqpn=(FszhAgm}zJS4RW6oMsJLtrePg4h<#32y)o0!4jR-xC*0ncVI4F& z`ke53W2RvpG&=g6aC>8h88murG)&$YmvBr6jb0l~xJS-;WBfY;a|aEmpwC7VAszR| z0Fh+xpy3C#%SOZEjq&dY>>V@?*=Sh2F&>G%gT^5n4Tm?z3l)0@jbk<%25(H5B>oN> z^gbud-k5-e!ryuMB(*%zbEX&oW7iK z(E6Nk7OJ%H^$MTNEm~TB?sE{{6SexBuotRd(?a`#C=Y+jbH#Gi3 zPLRHl&rti|n?!M+lL3X=|0SlC$tT_Kw<|%YGoL0Kox2W(FxzEXfLY-ZBo=d6DsGgC3s{@|i=VU;k z)|O};Df*|ZSJP!jhwre_3@8*ls015o2Ryyc$$&zI%{WD4R&}h>;XC@A3@Ef{&sg;p zcfiy8oQxE4I7`&u=VW-Hj{i6FZ|{-PjzDE^-K2a#BNru>v(ZJP2!;vaN|{Ch-K b{Mq;qLEZ}h@(