Made blob gamemode work, removed ninjas because needs overhaul, optimized some strings

This commit is contained in:
ZomgPonies
2013-09-08 11:39:33 -04:00
parent ea91047ce2
commit a935863200
70 changed files with 1084 additions and 923 deletions
+14
View File
@@ -0,0 +1,14 @@
// Camera mob, used by AI camera and blob.
/mob/camera
name = "camera mob"
density = 0
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
invisibility = 101 // No one can see us
move_on_shuttle = 0
/mob/camera/experience_pressure_difference()
return
-259
View File
@@ -1,259 +0,0 @@
/mob/living/blob
name = "blob fragment"
real_name = "blob fragment"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_spore_temp"
pass_flags = PASSBLOB
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
var/ghost_name = "Unknown"
var/creating_blob = 0
faction = "blob"
use_me = 0 //Blobs can't emote
New()
real_name += " [pick(rand(1, 99))]"
name = real_name
..()
say(var/message)
return//No talking for you
emote(var/act,var/m_type=1,var/message = null)
return
Life()
set invisibility = 0
set background = 1
clamp_values()
UpdateDamage()
if(health < 0)
src.dust()
proc/clamp_values()
AdjustStunned(0)
AdjustParalysis(0)
AdjustWeakened(0)
sleeping = 0
if(stat)
stat = CONSCIOUS
return
proc/UpdateDamage()
health = 60 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
return
death(gibbed)
if(key)
var/mob/dead/observer/ghost = new(src)
ghost.name = ghost_name
ghost.real_name = ghost_name
ghost.key = key
if (ghost.client)
ghost.client.eye = ghost
return ..(gibbed)
blob_act()
src << "The blob attempts to reabsorb you."
adjustToxLoss(20)
return
Process_Spacemove()
if(locate(/obj/effect/blob) in oview(1,src))
return 1
return (..())
/mob/living/blob/verb/create_node()
set category = "Blob"
set name = "Create Node"
set desc = "Create a Node."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)//We are on a blob
usr << "There is no blob here!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find a normal one."
creating_blob = 0
return
for(var/obj/effect/blob/node/blob in orange(5))
usr << "There is another node nearby, move more than 5 tiles away from it!"
creating_blob = 0
return
for(var/obj/effect/blob/factory/blob in orange(2))
usr << "There is a porus blob nearby, move more than 2 tiles away from it!"
creating_blob = 0
B.change_to("Node")
src.dust()
return
/mob/living/blob/verb/create_factory()
set category = "Blob"
set name = "Create Defense"
set desc = "Create a Spore producing blob."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
usr << "You must be on a blob!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find a normal one."
creating_blob = 0
return
for(var/obj/effect/blob/blob in orange(2))//Not right next to nodes/cores
if(istype(B,/obj/effect/blob/node))
usr << "There is a node nearby, move away from it!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/core))
usr << "There is a core nearby, move away from it!"
creating_blob = 0
return
if(istype(B,/obj/effect/blob/factory))
usr << "There is another porous blob nearby, move away from it!"
creating_blob = 0
return
B.change_to("Factory")
src.dust()
return
/mob/living/blob/verb/revert()
set category = "Blob"
set name = "Purge Defense"
set desc = "Removes a porous blob."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
usr << "You must be on a blob!"
creating_blob = 0
return
if(!istype(B,/obj/effect/blob/factory))
usr << "Unable to use this blob, find another one."
creating_blob = 0
return
B.change_to("Normal")
src.dust()
return
/mob/living/blob/verb/spawn_blob()
set category = "Blob"
set name = "Create new blob"
set desc = "Attempts to create a new blob in this tile."
if(creating_blob) return
var/turf/T = get_turf(src)
creating_blob = 1
if(!T)
creating_blob = 0
return
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(B)
usr << "There is a blob here!"
creating_blob = 0
return
new/obj/effect/blob(src.loc)
src.dust()
return
///mob/proc/Blobize()
/client/proc/Blobcount()
set category = "Debug"
set name = "blobreport"
set desc = "blob report."
set hidden = 1
if(!holder)
src << "Only administrators may use this command."
return
if(ticker && ticker.mode)
src << "blobs: [blobs.len]"
src << "cores: [blob_cores.len]"
src << "nodes: [blob_nodes.len]"
return
/client/proc/Blobize()//Mostly stolen from the respawn command
set category = "Debug"
set name = "Ghostblob"
set desc = "Ghost into blobthing."
set hidden = 1
if(!holder)
src << "Only administrators may use this command."
return
var/input = input(src, "Please specify which key will be turned into a bloby.", "Key", "")
var/mob/dead/observer/G_found
if(!input)
var/list/ghosts = list()
for(var/mob/dead/observer/G in player_list)
ghosts += G
if(ghosts.len)
G_found = pick(ghosts)
else
for(var/mob/dead/observer/G in player_list)
if(G.client&&ckey(G.key)==ckey(input))
G_found = G
break
if(!G_found)//If a ghost was not found.
alert("There is no active key like that in the game or the person is not currently a ghost. Aborting command.")
return
if(G_found.client)
G_found.client.screen.len = null
var/mob/living/blob/B = new/mob/living/blob(locate(0,0,1))//temp area also just in case should do this better but tired
if(blob_cores.len > 0)
var/obj/effect/blob/core/core = pick(blob_cores)
if(core)
B.loc = core.loc
B.ghost_name = G_found.real_name
if (G_found.client)
G_found.client.mob = B
B.verbs += /mob/living/blob/verb/create_node
B.verbs += /mob/living/blob/verb/create_factory
B << "<B>You are now a blob fragment.</B>"
B << "You are a weak bit that has temporarily broken off of the blob."
B << "If you stay on the blob for too long you will likely be reabsorbed."
B << "If you stray from the blob you will likely be killed by other organisms."
B << "You have the power to create a new blob node that will help expand the blob."
B << "To create this node you will have to be on a normal blob tile and far enough away from any other node."
B << "Check your Blob verbs and hit Create Node to build a node."
spawn(10)
del(G_found)
@@ -86,10 +86,10 @@
emote("deathgasp") //let the world KNOW WE ARE DEAD
//For ninjas exploding when they die.
if( istype(wear_suit, /obj/item/clothing/suit/space/space_ninja) && wear_suit:s_initialized )
/* if( istype(wear_suit, /obj/item/clothing/suit/space/space_ninja) && wear_suit:s_initialized )
src << browse(null, "window=spideros")//Just in case.
var/location = loc
explosion(location, 0, 0, 3, 4)
explosion(location, 0, 0, 3, 4)*/
update_canmove()
if(client) blind.layer = 0
@@ -164,8 +164,8 @@
if(mind.changeling)
stat("Chemical Storage", mind.changeling.chem_charges)
stat("Genetic Damage Time", mind.changeling.geneticdamage)
if (istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)&&wear_suit:s_initialized)
stat("Energy Charge", round(wear_suit:cell:charge/100))
// if (istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)&&wear_suit:s_initialized)
// stat("Energy Charge", round(wear_suit:cell:charge/100))
/mob/living/carbon/human/ex_act(severity)
@@ -256,7 +256,7 @@
show_message("\red The blob attacks you!")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee"))
return
/mob/living/carbon/human/meteorhit(O as obj)
+2 -2
View File
@@ -1165,7 +1165,7 @@
else
see_invisible = SEE_INVISIBLE_LIVING
seer = 0
/*
if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja))
var/obj/item/clothing/mask/gas/voice/space_ninja/O = wear_mask
switch(O.mode)
@@ -1186,7 +1186,7 @@
if(3)
sight |= SEE_TURFS
if(!druggy) see_invisible = SEE_INVISIBLE_LIVING
*/
if(glasses)
if(istype(glasses, /obj/item/clothing/glasses/meson))
sight |= SEE_TURFS
+1 -2
View File
@@ -2,8 +2,7 @@
/mob/living/Login()
..()
//Mind updates
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
sync_mind()
//Round specific stuff like hud updates
if(ticker && ticker.mode)
+2 -2
View File
@@ -427,7 +427,7 @@ var/list/ai_list = list()
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] took a swipe at []!</B>", M, src), 1)
return
/*
/mob/living/silicon/ai/attack_hand(mob/living/carbon/M as mob)
if(ishuman(M))//Checks to see if they are ninja
if(istype(M:gloves, /obj/item/clothing/gloves/space_ninja)&&M:gloves:candrain&&!M:gloves:draining)
@@ -437,7 +437,7 @@ var/list/ai_list = list()
M << "\red <b>ERROR</b>: \black Remote access channel disabled."
return
*/
/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob)
if(M.melee_damage_upper == 0)
M.emote("[M.friendly] [src]")
@@ -2,6 +2,8 @@
//
// The datum containing all the chunks.
var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
var/datum/cameranet/cameranet = new()
/datum/cameranet
@@ -13,16 +15,16 @@ var/datum/cameranet/cameranet = new()
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
return (chunks[key])
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
/datum/cameranet/proc/getCameraChunk(x, y, z)
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
if(!chunks[key])
chunks[key] = new /datum/camerachunk(null, x, y, z)
@@ -31,18 +33,18 @@ var/datum/cameranet/cameranet = new()
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(mob/aiEye/ai)
/datum/cameranet/proc/visibility(mob/camera/aiEye/ai)
// 0xf = 15
var/x1 = max(0, ai.x - 16) & ~0xf
var/y1 = max(0, ai.y - 16) & ~0xf
var/x2 = min(world.maxx, ai.x + 16) & ~0xf
var/y2 = min(world.maxy, ai.y + 16) & ~0xf
var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1)
var/list/visibleChunks = list()
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
visibleChunks += getCameraChunk(x, y, ai.z)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, ai.z)
var/list/remove = ai.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - ai.visibleCameraChunks
@@ -103,15 +105,15 @@ var/datum/cameranet/cameranet = new()
var/turf/T = get_turf(c)
if(T)
var/x1 = max(0, T.x - 8) & ~0xf
var/y1 = max(0, T.y - 8) & ~0xf
var/x2 = min(world.maxx, T.x + 8) & ~0xf
var/y2 = min(world.maxy, T.y + 8) & ~0xf
var/x1 = max(0, T.x - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
//world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]"
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
if(chunkGenerated(x, y, T.z))
var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z)
if(choice == 0)
@@ -21,7 +21,7 @@
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/aiEye/ai)
/datum/camerachunk/proc/add(mob/camera/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks += src
@@ -34,7 +34,7 @@
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/aiEye/ai)
/datum/camerachunk/proc/remove(mob/camera/aiEye/ai)
if(!ai.ai)
return
ai.visibleCameraChunks -= src
@@ -81,11 +81,14 @@
if(!c.can_use())
continue
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
if(get_dist(point, c) > 24)
var/turf/point = locate(src.x + (CHUNK_SIZE / 2), src.y + (CHUNK_SIZE / 2), src.z)
if(get_dist(point, c) > CHUNK_SIZE + (CHUNK_SIZE / 2))
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
newVisibleTurfs[t] = t
// Removes turf that isn't in turfs.
@@ -102,7 +105,7 @@
if(t.obscured)
obscured -= t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
var/mob/camera/aiEye/m = eye
if(!m || !m.ai)
continue
if(m.ai.client)
@@ -116,32 +119,32 @@
obscured += t.obscured
for(var/eye in seenby)
var/mob/aiEye/m = eye
var/mob/camera/aiEye/m = eye
if(!m || !m.ai)
seenby -= m
continue
if(m.ai.client)
m.ai.client.images += t.obscured
changed = 0
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
x &= ~0xf
y &= ~0xf
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
src.x = x
src.y = y
src.z = z
for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z)))
for(var/obj/machinery/camera/c in range(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z)))
if(c.can_use())
cameras += c
for(var/turf/t in range(10, locate(x + 8, y + 8, z)))
if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16)
turfs[t] = t
for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z)))
turfs[t] = t
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
@@ -152,6 +155,9 @@
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
visibleTurfs[t] = t
// Removes turf that isn't in turfs.
@@ -3,40 +3,16 @@
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/aiEye
/mob/camera/aiEye
name = "Inactive AI Eye"
icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
density = 0
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
// Movement code. Returns 0 to stop air movement from moving it.
/mob/aiEye/Move()
return 0
// Hide popout menu verbs
/mob/aiEye/examine()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/pull()
set popup_menu = 0
set src = usr.contents
return 0
/mob/aiEye/point()
set popup_menu = 0
set src = usr.contents
return 0
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/aiEye/proc/setLoc(var/T)
/mob/camera/aiEye/proc/setLoc(var/T)
if(ai)
if(!isturf(ai.loc))
@@ -52,12 +28,15 @@
H.move_hologram()
/mob/camera/aiEye/Move()
return 0
// AI MOVEMENT
// The AI's "eye". Described on the top of the page.
/mob/living/silicon/ai
var/mob/aiEye/eyeobj = new()
var/mob/camera/aiEye/eyeobj = new()
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
@@ -49,8 +49,7 @@
// DOORS
// Simply updates the visibility of the area when it opens/closes/destroyed.
/obj/machinery/door/update_nearby_tiles(need_rebuild)
. = ..(need_rebuild)
/obj/machinery/door/proc/update_freelok_sight()
// Glass door glass = 1
// don't check then?
if(!glass && cameranet)
+24 -24
View File
@@ -120,26 +120,26 @@ var/datum/paiController/paiController // Global handler for pAI candidates
</style>
"}
dat += "<p class=\"top\">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>"
dat += "<table>"
dat += "<tr class=\"d0\"><td>Name:</td><td>[candidate.name]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=name;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td></tr>"
dat += {"<p class=\"top\">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
<table>
<tr class=\"d0\"><td>Name:</td><td>[candidate.name]</td></tr>
<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=name;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td></tr>
dat += "<tr class=\"d0\"><td>Description:</td><td>[candidate.description]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=desc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td></tr>"
<tr class=\"d0\"><td>Description:</td><td>[candidate.description]</td></tr>
<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=desc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td></tr>
dat += "<tr class=\"d0\"><td>Preferred Role:</td><td>[candidate.role]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=role;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td></tr>"
<tr class=\"d0\"><td>Preferred Role:</td><td>[candidate.role]</td></tr>
<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=role;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td></tr>
dat += "<tr class=\"d0\"><td>OOC Comments:</td><td>[candidate.comments]</td></tr>"
dat += "<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=ooc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td></tr>"
<tr class=\"d0\"><td>OOC Comments:</td><td>[candidate.comments]</td></tr>
<tr class=\"d1\"><td><a href='byond://?src=\ref[src];option=ooc;new=1;candidate=\ref[candidate]'>\[Edit\]</a></td><td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td></tr>
dat += "</table>"
</table>
dat += "<br>"
dat += "<h3><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]'>Submit Personality</a></h3><br>"
dat += "<a href='byond://?src=\ref[src];option=save;new=1;candidate=\ref[candidate]'>Save Personality</a><br>"
dat += "<a href='byond://?src=\ref[src];option=load;new=1;candidate=\ref[candidate]'>Load Personality</a><br>"
<br>
<h3><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]'>Submit Personality</a></h3><br>
<a href='byond://?src=\ref[src];option=save;new=1;candidate=\ref[candidate]'>Save Personality</a><br>
<a href='byond://?src=\ref[src];option=load;new=1;candidate=\ref[candidate]'>Load Personality</a><br>"}
M << browse(dat, "window=paiRecruit")
@@ -173,19 +173,19 @@ var/datum/paiController/paiController // Global handler for pAI candidates
background-color: #99CC99; color: black;
}
</style>
"}
dat += "<p class=\"top\">Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
dat += "<table>"
<p class=\"top\">Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>
<table>"}
for(var/datum/paiCandidate/c in available)
dat += "<tr class=\"d0\"><td>Name:</td><td>[c.name]</td></tr>"
dat += "<tr class=\"d1\"><td>Description:</td><td>[c.description]</td></tr>"
dat += "<tr class=\"d0\"><td>Preferred Role:</td><td>[c.role]</td></tr>"
dat += "<tr class=\"d1\"><td>OOC Comments:</td><td>[c.comments]</td></tr>"
dat += "<tr class=\"d2\"><td><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]'>\[Download [c.name]\]</a></td><td></td></tr>"
dat += {"<tr class=\"d0\"><td>Name:</td><td>[c.name]</td></tr>
<tr class=\"d1\"><td>Description:</td><td>[c.description]</td></tr>
<tr class=\"d0\"><td>Preferred Role:</td><td>[c.role]</td></tr>
<tr class=\"d1\"><td>OOC Comments:</td><td>[c.comments]</td></tr>
<tr class=\"d2\"><td><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]'>\[Download [c.name]\]</a></td><td></td></tr>
dat += "</table>"
</table>"}
user << browse(dat, "window=findPai")
@@ -374,6 +374,9 @@
adjustBruteLoss(60)
updatehealth()
return 1
else
gib()
return 1
return 0
// this function shows information about the malf_ai gameplay type in the status screen
@@ -942,12 +945,12 @@
var/obj/item/broken_device = cell_component.wrapped
user << "You remove \the [broken_device]."
user.put_in_active_hand(broken_device)
/*
if(ishuman(user))
if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining)
call(/obj/item/clothing/gloves/space_ninja/proc/drain)("CYBORG",src,user:wear_suit)
return
*/
/mob/living/silicon/robot/proc/allowed(mob/M)
//check if it doesn't require any access at all
if(check_access(null))
@@ -14,9 +14,9 @@
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "pokes the"
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
stop_automated_movement_when_pulled = 0
maxHealth = 60
health = 60
@@ -43,17 +43,21 @@
desc = ""
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "pokes"
response_harm = "hits"
/mob/living/simple_animal/hostile/bear/Move()
..()
if(stat != DEAD)
if(loc && istype(loc,/turf/space))
icon_state = "bear"
else
icon_state = "bearfloor"
/mob/living/simple_animal/hostile/bear/Life()
. =..()
if(!.)
return
if(loc && istype(loc,/turf/space))
icon_state = "bear"
else
icon_state = "bearfloor"
switch(stance)
@@ -61,7 +65,7 @@
stop_automated_movement = 1
stance_step++
if(stance_step >= 10) //rests for 10 ticks
if(target_mob && target_mob in ListTargets(10))
if(target && target 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
@@ -69,15 +73,15 @@
if(HOSTILE_STANCE_ALERT)
stop_automated_movement = 1
var/found_mob = 0
if(target_mob && target_mob in ListTargets(10))
if(!(SA_attackable(target_mob)))
if(target && target in ListTargets())
if(!(SA_attackable(target)))
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
src.dir = get_dir(src,target) //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]" ) )
var/action = pick( list( "growls at [target]", "stares angrily at [target]", "prepares to attack [target]", "closely watches [target]" ) )
if(action)
emote(action)
if(!found_mob)
@@ -102,18 +106,18 @@
if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING)
stance = HOSTILE_STANCE_ALERT
stance_step = 6
target_mob = user
target = 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
target = M
..()
/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/check_drift = 0)
return //No drifting in space for space bears!
return 1 //No drifting in space for space bears!
/mob/living/simple_animal/hostile/bear/FindTarget()
. = ..()
@@ -125,22 +129,22 @@
..(5)
/mob/living/simple_animal/hostile/bear/AttackingTarget()
emote( pick( list("slashes at [target_mob]", "bites [target_mob]") ) )
emote( pick( list("slashes at [target]", "bites [target]") ) )
var/damage = rand(20,30)
if(ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
if(ishuman(target))
var/mob/living/carbon/human/H = target
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
else if(isliving(target))
var/mob/living/L = target
L.adjustBruteLoss(damage)
return L
else if(istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
else if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.attack_animal(src)
return M
@@ -34,7 +34,7 @@
max_n2 = 0
minbodytemp = 0
break_stuff_probability = 2
faction = "carp"
@@ -17,9 +17,9 @@
turns_per_move = 5
see_in_dark = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "pokes the"
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
stop_automated_movement_when_pulled = 0
maxHealth = 200
health = 200
@@ -33,7 +33,6 @@
var/busy = 0
pass_flags = PASSTABLE
move_to_delay = 6
speed = 3
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/giant_spider/nurse
@@ -65,8 +64,8 @@
/mob/living/simple_animal/hostile/giant_spider/AttackingTarget()
..()
if(isliving(target_mob))
var/mob/living/L = target_mob
if(isliving(target))
var/mob/living/L = target
if(L.reagents)
L.reagents.add_reagent("toxin", poison_per_bite)
if(prob(poison_per_bite))
@@ -83,7 +82,7 @@
for(var/turf/T in orange(20, src))
move_targets.Add(T)*/
stop_automated_movement = 1
walk_to(src, pick(orange(20, src)), 1, move_to_delay)
Goto(pick(orange(20, src)), move_to_delay)
spawn(50)
stop_automated_movement = 0
walk(src,0)
@@ -105,10 +104,10 @@
if(!busy && prob(30))
//first, check for potential food nearby to cocoon
for(var/mob/living/C in can_see)
if(C.stat)
if(C.stat && !istype(C,/mob/living/simple_animal/hostile/giant_spider))
cocoon_target = C
busy = MOVING_TO_TARGET
walk_to(src, C, 1, move_to_delay)
Goto(C, move_to_delay)
//give up if we can't reach them after 10 seconds
GiveUp(C)
return
@@ -150,7 +149,7 @@
cocoon_target = O
busy = MOVING_TO_TARGET
stop_automated_movement = 1
walk_to(src, O, 1, move_to_delay)
Goto(O, move_to_delay)
//give up if we can't reach them after 10 seconds
GiveUp(O)
@@ -1,27 +1,23 @@
/mob/living/simple_animal/hostile
faction = "hostile"
var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior
var/mob/living/target_mob
var/target
var/attack_same = 0
var/ranged = 0
var/rapid = 0
var/projectiletype
var/projectilesound
var/casingtype
var/move_to_delay = 4 //delay for the automated movement.
var/move_to_delay = 2 //delay for the automated movement.
var/list/friends = list()
var/break_stuff_probability = 10
var/vision_range = 10
stop_automated_movement_when_pulled = 0
var/destroy_surroundings = 1
/mob/living/simple_animal/hostile/proc/FindTarget()
var/atom/T = null
stop_automated_movement = 0
for(var/atom/A in ListTargets(10))
if(A == src)
continue
for(var/atom/A in ListTargets())
var/atom/F = Found(A)
if(F)
@@ -36,72 +32,68 @@
continue
else
if(!L.stat)
stance = HOSTILE_STANCE_ATTACK
T = L
break
else if(istype(A, /obj/mecha)) // Our line of sight stuff was already done in ListTargets().
var/obj/mecha/M = A
if (M.occupant)
stance = HOSTILE_STANCE_ATTACK
T = M
break
if(istype(A, /obj/machinery/bot))
var/obj/machinery/bot/B = A
if (B.health > 0)
stance = HOSTILE_STANCE_ATTACK
T = B
break
return T
/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)
target = new_target
stance = HOSTILE_STANCE_ATTACK
return
/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay)
walk_to(src, target, 1, delay)
/mob/living/simple_animal/hostile/proc/Found(var/atom/A)
return
/mob/living/simple_animal/hostile/proc/MoveToTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
stance = HOSTILE_STANCE_IDLE
if(target_mob in ListTargets(10))
if(!target || SA_attackable(target))
LoseTarget()
if(target in ListTargets())
if(ranged)
if(get_dist(src, target_mob) <= 6)
OpenFire(target_mob)
if(get_dist(src, target) <= 6)
OpenFire(target)
else
walk_to(src, target_mob, 1, move_to_delay)
Goto(target, move_to_delay)
else
stance = HOSTILE_STANCE_ATTACKING
walk_to(src, target_mob, 1, move_to_delay)
Goto(target, move_to_delay)
/mob/living/simple_animal/hostile/proc/AttackTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
if(!target || SA_attackable(target))
LoseTarget()
return 0
if(!(target_mob in ListTargets(10)))
if(!(target in ListTargets()))
LostTarget()
return 0
if(get_dist(src, target_mob) <= 1) //Attacking
if(get_dist(src, target) <= 1) //Attacking
AttackingTarget()
return 1
/mob/living/simple_animal/hostile/proc/AttackingTarget()
if(isliving(target_mob))
var/mob/living/L = target_mob
if(isliving(target))
var/mob/living/L = target
L.attack_animal(src)
return L
if(istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
if(istype(target,/obj/mecha))
var/obj/mecha/M = target
M.attack_animal(src)
return M
if(istype(target_mob,/obj/machinery/bot))
var/obj/machinery/bot/B = target_mob
B.attack_animal(src)
/mob/living/simple_animal/hostile/proc/LoseTarget()
stance = HOSTILE_STANCE_IDLE
target_mob = null
target = null
walk(src, 0)
/mob/living/simple_animal/hostile/proc/LostTarget()
@@ -109,9 +101,17 @@
walk(src, 0)
/mob/living/simple_animal/hostile/proc/ListTargets(var/dist = 7)
var/list/L = hearers(src, dist)
L += mechas_list
/mob/living/simple_animal/hostile/proc/ListTargets(var/override = -1)
// Allows you to override how much the mob can see. Defaults to vision_range if none is entered.
if(override == -1)
override = vision_range
var/list/L = hearers(src, override)
for(var/obj/mecha/M in mechas_list)
// Will check the distance before checking the line of sight, if the distance is small enough.
if(get_dist(M, src) <= override && can_see(src, M, override))
L += M
return L
/mob/living/simple_animal/hostile/Die()
@@ -130,20 +130,19 @@
if(!stat)
switch(stance)
if(HOSTILE_STANCE_IDLE)
target_mob = FindTarget()
var/new_target = FindTarget()
GiveTarget(new_target)
if(HOSTILE_STANCE_ATTACK)
if(destroy_surroundings)
DestroySurroundings()
DestroySurroundings()
MoveToTarget()
if(HOSTILE_STANCE_ATTACKING)
if(destroy_surroundings)
DestroySurroundings()
DestroySurroundings()
AttackTarget()
/mob/living/simple_animal/hostile/proc/OpenFire(target_mob)
var/target = target_mob
/mob/living/simple_animal/hostile/proc/OpenFire(var/the_target)
var/target = the_target
visible_message("\red <b>[src]</b> fires at [target]!", 1)
var/tturf = get_turf(target)
@@ -166,7 +165,7 @@
new casingtype
stance = HOSTILE_STANCE_IDLE
target_mob = null
target = null
return
@@ -189,8 +188,7 @@
return
/mob/living/simple_animal/hostile/proc/DestroySurroundings()
if(prob(break_stuff_probability))
for(var/dir in cardinal) // North, South, East, West
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
obstacle.attack_animal(src)
for(var/dir in cardinal) // North, South, East, West
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
obstacle.attack_animal(src)
@@ -22,7 +22,6 @@
speed = 8
projectiletype = /obj/item/projectile/beam/drone
projectilesound = 'sound/weapons/laser3.ogg'
destroy_surroundings = 0
var/datum/effect/effect/system/ion_trail_follow/ion_trail
//the drone randomly switches between these states because it's malfunctioning
@@ -24,9 +24,9 @@
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/response_help = "pokes"
var/response_disarm = "shoves"
var/response_harm = "hits"
var/harm_intent_damage = 3
//Temperature effect
@@ -96,7 +96,7 @@
AdjustParalysis(-1)
//Movement
if(!client && !stop_automated_movement && wander && !anchored)
if(!client && !stop_automated_movement && wander)
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)
@@ -217,6 +217,11 @@
new meat_type(src.loc)
..()
/mob/living/simple_animal/blob_act()
adjustBruteLoss(20)
return
/mob/living/simple_animal/say_quote(var/text)
if(speak_emote && speak_emote.len)
var/emote = pick(speak_emote)
@@ -224,10 +229,14 @@
return "[emote], \"[text]\""
return "says, \"[text]\"";
/mob/living/simple_animal/emote(var/act, var/type, var/desc)
/mob/living/simple_animal/emote(var/act)
if(stat)
return
if(act)
if(act == "scream") act = "whimper" //ugly hack to stop animals screaming when crushed :P
..(act, type, desc)
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("<B>[src]</B> [act].")
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob)
if(M.melee_damage_upper == 0)
@@ -236,7 +245,7 @@
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
for(var/mob/O in viewers(src, null))
O.show_message("\red <B>[M]</B> [M.attacktext] [src]!", 1)
O.show_message("\red <B>\The [M]</B> [M.attacktext] [src]!", 1)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
@@ -256,15 +265,15 @@
if (health > 0)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\blue [M] [response_help] [src]")
O.show_message("\blue [M] [response_help] [src].")
if("grab")
if (M == src)
if (M == src || anchored)
return
if (!(status_flags & CANPUSH))
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src )
M.put_in_active_hand(G)
@@ -277,11 +286,11 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
if("hurt", "disarm")
if("harm", "disarm")
adjustBruteLoss(harm_intent_damage)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] [response_harm] [src]")
O.show_message("\red [M] [response_harm] [src]!")
return
@@ -295,12 +304,12 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1)
if ("grab")
if(M == src)
if(M == src || anchored)
return
if(!(status_flags & CANPUSH))
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src )
M.put_in_active_hand(G)
@@ -313,7 +322,7 @@
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
if("hurt", "disarm")
if("harm", "disarm")
var/damage = rand(15, 30)
visible_message("\red <B>[M] has slashed at [src]!</B>")
adjustBruteLoss(damage)
@@ -344,7 +353,7 @@
if(M.Victim) return // can't attack while eating!
visible_message("\red <B>The [M.name] glomps [src]!</B>")
visible_message("\red <B>[M.name] glomps [src]!</B>")
var/damage = rand(1, 3)
@@ -366,22 +375,32 @@
var/obj/item/stack/medical/MED = O
if(health < maxHealth)
if(MED.amount >= 1)
adjustBruteLoss(-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]")
if(MED.heal_brute >= 1)
adjustBruteLoss(-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 [MED] on [src]")
return
else
user << "\blue [MED] won't help at all."
return
else
user << "\blue [src] is at full health."
return
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.
user << "\blue [src] is dead, medical items won't bring it back to life."
return
else 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()
return
else
if(O.force)
var/damage = O.force
@@ -390,12 +409,12 @@
adjustBruteLoss(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]. ")
M.show_message("\red \b "+"[src] has been attacked with [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]. ")
M.show_message("\red [user] gently taps [src] with [O]. ")
@@ -438,26 +457,16 @@
/mob/living/simple_animal/adjustBruteLoss(damage)
health = Clamp(health - damage, 0, maxHealth)
if(health < 1)
Die()
/mob/living/simple_animal/proc/SA_attackable(target_mob)
if (isliving(target_mob))
var/mob/living/L = target_mob
if(!L.stat && L.health >= 0)
return (0)
if (istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
/mob/living/simple_animal/proc/SA_attackable(target)
if (isliving(target))
var/mob/living/L = target
if(!L.stat)
return 0
if (istype(target,/obj/mecha))
var/obj/mecha/M = target
if (M.occupant)
return (0)
if (istype(target_mob,/obj/machinery/bot))
var/obj/machinery/bot/B = target_mob
if(B.health > 0)
return (0)
return (1)
//Call when target overlay should be added/removed
/mob/living/simple_animal/update_targeted()
if(!targeted_by && target_locked)
del(target_locked)
overlays = null
if (targeted_by && target_locked)
overlays += target_locked
return 0
return 1
+1
View File
@@ -160,6 +160,7 @@
var/faction = "neutral" //Used for checking whether hostile simple animals will attack you, possibly more stuff later
var/move_on_shuttle = 1 // Can move on the shuttle.
//Generic list for proc holders. Only way I can see to enable certain verbs/procs. Should be modified if needed.
var/proc_holder_list[] = list()//Right now unused.
+5
View File
@@ -115,6 +115,11 @@ proc/isobserver(A)
return 1
return 0
proc/isovermind(A)
if(istype(A, /mob/camera/blob))
return 1
return 0
proc/isorgan(A)
if(istype(A, /datum/organ/external))
return 1
+5 -4
View File
@@ -226,11 +226,13 @@
if(mob.control_object) Move_object(direct)
if(isobserver(mob)) return mob.Move(n,direct)
if(world.time < move_delay) return
if(moving) return 0
if(isAI(mob)) return AIMove(n,direct,mob)
if(world.time < move_delay) return
if(!isliving(mob)) return mob.Move(n,direct)
if(moving) return 0
if(!mob) return
@@ -241,7 +243,6 @@
if(mob.stat==2) return
if(isAI(mob)) return AIMove(n,direct,mob)
if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var