Merge pull request #711 from tigercat2000/Spesswormoverhaul

Spaceworm overhaul (-tg-port)
This commit is contained in:
ZomgPonies
2015-04-02 14:07:41 -04:00
6 changed files with 343 additions and 203 deletions
@@ -26,7 +26,7 @@
var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled
var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead.
var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
var/AIenabled = 1 //Badminnery and general AI toggle.
/mob/living/simple_animal/hostile/Life()
@@ -34,7 +34,7 @@
if(!.)
walk(src, 0)
return 0
if(client)
if(client || !AIenabled)
return 0
if(!stat)
switch(stance)
@@ -0,0 +1,337 @@
//Worm Segments, Dummy, has no AI, relies on the head.
/mob/living/simple_animal/hostile/spaceWorm
name = "space worm segment"
desc = "A part of a space worm."
icon = 'icons/mob/animal.dmi'
icon_state = "spaceworm"
icon_living = "spaceworm"
icon_dead = "spacewormdead"
status_flags = 0
speak_emote = list("screeches")
emote_hear = list("screeches")
response_help = "touches"
response_disarm = "flails at"
response_harm = "punches"
harm_intent_damage = 2
maxHealth = 50
health = 50
stop_automated_movement = 1
animate_movement = SYNC_STEPS
minbodytemp = 0
maxbodytemp = 350
min_oxy = 0
max_co2 = 0
max_tox = 0
a_intent = "harm" //so they don't get pushed around
environment_smash = 1
speed = -1
AIenabled = 0 //The body isn't conscious
anchored = 1 //otherwise people can literally fucking pull spaceworms apart
faction = list("spaceworms")
var/mob/living/simple_animal/hostile/spaceWorm/previousWorm //next/previous segments, correspondingly
var/mob/living/simple_animal/hostile/spaceWorm/nextWorm //head is the nextest segment
var/mob/living/simple_animal/hostile/spaceWorm/wormHead/myHead //Can be the same as next, just a general reference to the main worm.
var/stomachProcessProbability = 50
var/digestionProbability = 20
var/atom/currentlyEating //what the worm is currently eating
var/plasmaPoopPotential = 5 //this mainly exists for the name
/mob/living/simple_animal/hostile/spaceWorm/Process_Spacemove(var/check_drift = 0)
return 1 //space worms can flyyyyyy
//Worm Head, Controls the AI for the entire worm "entity"
/mob/living/simple_animal/hostile/spaceWorm/wormHead
name = "space worm head"
icon_state = "spacewormhead"
icon_living = "spacewormhead"
icon_dead = "spacewormdead"
//Stronger than normal segments
maxHealth = 125
health = 125
melee_damage_lower = 10//was 20, dear god
melee_damage_upper = 15//was 25, dear god
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
animate_movement = SLIDE_STEPS
AIenabled = 1//The head is conscious
stop_automated_movement = 0 //Ditto ^
faction = list("spaceworms") //head and body both have this faction JIC
//head specific variables
var/spawnWithSegments = 6
var/list/totalWormSegments = list() //doesn't contain src
var/catastrophicDeathProb = 15 //15% chance for the death of the head to kill the whole thing
/mob/living/simple_animal/hostile/spaceWorm/wormHead/New(var/location, var/segments = spawnWithSegments)
..()
if(!src)//This is to prevent a runtime.
return
myHead = src //It's it's own head.
//Used in the for to attach each worm segment to the next in the sequence, instead of all of them to src
var/mob/living/simple_animal/hostile/spaceWorm/currentWormSeg = src
for(var/i = 1 to segments)
var/mob/living/simple_animal/hostile/spaceWorm/newSegment = new /mob/living/simple_animal/hostile/spaceWorm(loc)
currentWormSeg.Attach(newSegment)
currentWormSeg = newSegment
for(var/mob/living/simple_animal/hostile/spaceWorm/SW in totalWormSegments)
SW.update_icon()
/mob/living/simple_animal/hostile/spaceWorm/wormHead/update_icon()
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
icon_state = "spacewormhead[previousWorm ? 1 : 0]"
if(previousWorm)
dir = get_dir(previousWorm,src)
else
icon_state = "spacewormheaddead"
for(var/mob/living/simple_animal/hostile/spaceWorm/SW in totalWormSegments)
if(SW == src)//incase src ends up in here we don't want an infinite loop
continue
SW.update_icon()
//Try to move onto target's turf and eat them
/mob/living/simple_animal/hostile/spaceWorm/wormHead/AttackingTarget()
..()
attemptToEat(target)
//Attempt to eat things we bump into, Mobs, Walls, Clowns
/mob/living/simple_animal/hostile/spaceWorm/wormHead/Bump(atom/obstacle)
attemptToEat(obstacle)
//Attempt to eat things, only the head can eat
/mob/living/simple_animal/hostile/spaceWorm/wormHead/proc/attemptToEat(var/atom/noms)
if(currentlyEating == noms) //currentlyEating is always undefined at the end, so don't eat the same thing twice
return
if(istype(noms, /obj/structure/window))
return
if(istype(noms, /obj/structure/grille)) //these three bug-out and won't work, so just ignore them
return
if(istype(noms, /obj/machinery/door/window))
return
if(!noms)
return
currentlyEating = noms
var/nomDelay = 25
var/turf/simulated/wall/W
if(noms in totalWormSegments)
return //Trying to eat part of self.
if(istype(noms, /turf))
if(istype(noms, /turf/simulated/wall))
W = noms
nomDelay *= 2
if(W.walltype == "rwall")
nomDelay *= 2
else
return
var/ufnomDelay = nomDelay * 0.1
src.visible_message("<span class='userdanger'>\the [src] starts to eat \the [noms]!</span>","<span class='notice'>You start to eat \the [noms]. (This will take about [ufnomDelay] seconds.)</span>","<span class='userdanger'>You hear gnashing.</span>") //inform everyone what the fucking worm is doing.
if(do_after(src, nomDelay,5,0))
if(noms && Adjacent(noms) && (currentlyEating == noms))//It exists, were next to it, and it's still the thing were eating
if(W)
W.ChangeTurf(/turf/simulated/floor/plating)
new /obj/item/stack/sheet/metal(src, plasmaPoopPotential)
currentlyEating = null //ffs, unstore this
src.visible_message("<span class='userdanger'>\the [src] eats \the [noms]!</span>","<span class='notice'>You eat \the [noms]!</span>","<span class=userdanger'>You hear gnashing.</span>") //inform everyone what the fucking worm is doing.
else
currentlyEating = null
contents += noms
src.visible_message("<span class='userdanger'>\the [src] eats \the [noms]!</span>","<span class='notice'>You eat \the [noms]!</span>","<span class=userdanger'>You hear gnashing.</span>") //inform everyone what the fucking worm is doing.
if(ismob(noms))
var/mob/M = noms //typecast because noms isn't movable
M.loc = src //because just setting a mob loc to null breaks the camera and such
else
currentlyEating = null
else
currentlyEating = null //JIC
//Harder to kill the head, but it can kill off the whole worm
/mob/living/simple_animal/hostile/spaceWorm/wormHead/Die()
..()
if(prob(catastrophicDeathProb))
for(var/mob/living/simple_animal/hostile/spaceWorm/SW in totalWormSegments)
SW.Die()
/mob/living/simple_animal/hostile/spaceWorm/Life()
if(nextWorm && !(Adjacent(nextWorm)))
Detach(0)
if(stat == DEAD)
if(previousWorm)
previousWorm.Detach(0)
if(nextWorm)
Detach(1)
if(prob(stomachProcessProbability))
ProcessStomach()
update_icon()//While most mobs don't call this on Life(), the worm would probably look stupid without it
//Plus the worm's update_icon() isn't as beefy.
..() //Really high fuckin priority that this is at the bottom.
//if a chunk a destroyed, make a new worm out of the split halves
/mob/living/simple_animal/hostile/spaceWorm/Destroy()
if(previousWorm)
previousWorm.Detach(0)
..()
//Move all segments if one piece moves.
/mob/living/simple_animal/hostile/spaceWorm/Move()
var/segmentNextPos = loc
if(..())
if(previousWorm)
previousWorm.Move(segmentNextPos)
update_icon()
//Update the appearence of this big weird chain-worm-thingy
/mob/living/simple_animal/hostile/spaceWorm/proc/update_icon()
if(stat != DEAD)
if(previousWorm)
icon_state = "spaceworm[get_dir(src,previousWorm) | get_dir(src,nextWorm)]"
else
icon_state = "spacewormtail"//end of rine
dir = get_dir(src,nextWorm)
else
icon_state = "spacewormdead"
//Add a new worm segment
/mob/living/simple_animal/hostile/spaceWorm/proc/Attach(var/mob/living/simple_animal/hostile/spaceWorm/toAttach)
if(!toAttach)
return
previousWorm = toAttach
toAttach.nextWorm = src
if(myHead)
if(toAttach.myHead)
toAttach.myHead.totalWormSegments -= src
toAttach.myHead = myHead
myHead.totalWormSegments |= toAttach
//if toAttach is part of another worm, disconnect all those parts and connect them to the new worm.
var/mob/living/simple_animal/hostile/spaceWorm/isPrevWorm
if(toAttach.previousWorm)
isPrevWorm = toAttach.previousWorm
while(isPrevWorm)
if(isPrevWorm.previousWorm)
if(isPrevWorm.myHead)
isPrevWorm.myHead.totalWormSegments -=isPrevWorm.previousWorm
toAttach.myHead.totalWormSegments |= isPrevWorm.previousWorm
isPrevWorm = isPrevWorm.previousWorm
else
isPrevWorm = null
update_icons()
//Remove a worm segment
/mob/living/simple_animal/hostile/spaceWorm/proc/Detach(var/die = 0)
var/mob/living/simple_animal/hostile/spaceWorm/wormHead/newHead = new /mob/living/simple_animal/hostile/spaceWorm/wormHead(loc,0)
var/mob/living/simple_animal/hostile/spaceWorm/newHeadPrev
if(previousWorm)
newHeadPrev = previousWorm
previousWorm = null
if(newHeadPrev)
newHead.Attach(newHeadPrev)
if(myHead)
myHead.totalWormSegments -= src
if(die)
newHead.Die()
qdel(src)
/mob/living/simple_animal/hostile/spaceWorm/Die()
..()
if(myHead)
myHead.totalWormSegments -= src
//Process nom noms, things we've eaten have a chance to become plasma
/mob/living/simple_animal/hostile/spaceWorm/proc/ProcessStomach()
for(var/atom/movable/stomachContent in contents)
if(prob(digestionProbability))
new /obj/item/stack/sheet/mineral/plasma(src, plasmaPoopPotential)
if(ismob(stomachContent))
var/mob/M = stomachContent
M.ghostize() //because qdelling an entire mob without ghosting it is BAD
qdel(stomachContent)
if(previousWorm)
for(var/atom/movable/stomachContent in contents) //move it along the digestive tract
contents -= stomachContent
previousWorm.contents += stomachContent
if(ismob(stomachContent))
stomachContent.loc = previousWorm //weird shit happens otherwise
else
var/turf/T = get_turf(src)
for(var/atom/movable/stomachContent in contents)
contents -= stomachContent
stomachContent.loc = T
//Looks weird otherwise.
/mob/living/simple_animal/hostile/spaceWorm/float(on)
return
//Jiggle the whole worm forwards towards the next segment
/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A)
..()
if(previousWorm)
previousWorm.do_attack_animation(src)
@@ -1,197 +0,0 @@
/mob/living/simple_animal/space_worm
name = "space worm segment"
desc = "A part of a space worm."
icon = 'icons/mob/animal.dmi'
icon_state = "spaceworm"
icon_living = "spaceworm"
icon_dead = "spacewormdead"
status_flags = 0
speak_emote = list("transmits") //not supposed to be used under AI control
emote_hear = list("transmits") //I'm just adding it so it doesn't runtime if controlled by player who speaks
response_help = "touches"
response_disarm = "flails at"
response_harm = "punches the"
harm_intent_damage = 2
maxHealth = 30
health = 30
stop_automated_movement = 1
animate_movement = SYNC_STEPS
minbodytemp = 0
maxbodytemp = 350
min_oxy = 0
max_co2 = 0
max_tox = 0
a_intent = "harm" //so they don't get pushed around
speed = -1
var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly
var/mob/living/simple_animal/space_worm/next //head is the nextest segment
var/stomachProcessProbability = 50
var/digestionProbability = 20
var/flatPlasmaValue = 5 //flat plasma amount given for non-items
var/atom/currentlyEating //what the worm is currently eating
var/eatingDuration = 0 //how long he's been eating it for
head
name = "space worm head"
icon_state = "spacewormhead"
icon_living = "spacewormhead"
icon_dead = "spacewormdead"
maxHealth = 20
health = 20
melee_damage_lower = 10
melee_damage_upper = 15
attacktext = "bites"
animate_movement = SLIDE_STEPS
New(var/location, var/segments = 6)
..()
var/mob/living/simple_animal/space_worm/current = src
for(var/i = 1 to segments)
var/mob/living/simple_animal/space_worm/newSegment = new /mob/living/simple_animal/space_worm(loc)
current.Attach(newSegment)
current = newSegment
update_icon()
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
icon_state = "spacewormhead[previous?1:0]"
if(previous)
dir = get_dir(previous,src)
else
icon_state = "spacewormheaddead"
Life()
..()
if(next && !(next in view(src,1)))
Detach()
if(stat == DEAD) //dead chunks fall off and die immediately
if(previous)
previous.Detach()
if(next)
Detach(1)
if(prob(stomachProcessProbability))
ProcessStomach()
update_icon()
return
Destroy() //if a chunk a destroyed, make a new worm out of the split halves
if(previous)
previous.Detach()
..()
Move()
var/attachementNextPosition = loc
if(..())
if(previous)
previous.Move(attachementNextPosition)
update_icon()
Bump(atom/obstacle)
if(currentlyEating != obstacle)
currentlyEating = obstacle
eatingDuration = 0
if(!AttemptToEat(obstacle))
eatingDuration++
else
currentlyEating = null
eatingDuration = 0
return
proc/update_icon() //only for the sake of consistency with the other update icon procs
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
if(previous) //midsection
icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below
else //tail
icon_state = "spacewormtail"
dir = get_dir(src,next) //next will always be present since it's not a head and if it's dead, it goes in the other if branch
else
icon_state = "spacewormdead"
return
proc/AttemptToEat(var/atom/target)
if(istype(target,/turf/simulated/wall))
if((!istype(target,/turf/simulated/wall/r_wall) && eatingDuration >= 100) || eatingDuration >= 200) //need 20 ticks to eat an rwall, 10 for a regular one
var/turf/simulated/wall/wall = target
wall.ChangeTurf(/turf/simulated/floor)
new /obj/item/stack/sheet/metal(src, flatPlasmaValue)
return 1
else if(istype(target,/atom/movable))
if(istype(target,/mob) || eatingDuration >= 50) //5 ticks to eat stuff like airlocks
var/atom/movable/objectOrMob = target
contents += objectOrMob
return 1
return 0
proc/Attach(var/mob/living/simple_animal/space_worm/attachement)
if(!attachement)
return
previous = attachement
attachement.next = src
return
proc/Detach(die = 0)
var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0)
var/mob/living/simple_animal/space_worm/newHeadPrevious = previous
previous = null //so that no extra heads are spawned
newHead.Attach(newHeadPrevious)
if(die)
newHead.Die()
del(src)
proc/ProcessStomach()
for(var/atom/movable/stomachContent in contents)
if(prob(digestionProbability))
if(istype(stomachContent,/obj/item/stack)) //converts to plasma, keeping the stack value
if(!istype(stomachContent,/obj/item/stack/sheet/mineral/plasma))
var/obj/item/stack/oldStack = stomachContent
new /obj/item/stack/sheet/mineral/plasma(src, oldStack.amount)
del(oldStack)
continue
else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class
var/obj/item/oldItem = stomachContent
new /obj/item/stack/sheet/mineral/plasma(src, oldItem.w_class)
del(oldItem)
continue
else
new /obj/item/stack/sheet/mineral/plasma(src, flatPlasmaValue) //just flat amount
del(stomachContent)
continue
if(previous)
for(var/atom/movable/stomachContent in contents) //transfer it along the digestive tract
previous.contents += stomachContent
else
for(var/atom/movable/stomachContent in contents) //or poop it out
loc.contents += stomachContent
return
+2 -2
View File
@@ -123,7 +123,7 @@
O.rename_self("ai",1)
. = O
qdel(src)
/mob/living/carbon/human/make_into_mask(var/should_gib = 0)
for(var/t in organs)
qdel(t)
@@ -383,7 +383,7 @@
if(!MP)
return 0 //Sanity, this should never happen.
if(ispath(MP, /mob/living/simple_animal/space_worm))
if(ispath(MP, /mob/living/simple_animal/hostile/spaceWorm))
return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning.
if(ispath(MP, /mob/living/simple_animal/construct/behemoth))