From 1d8dea23371adb86b812b72463fe294c7392e032 Mon Sep 17 00:00:00 2001 From: "noisomehollow@lycos.com" Date: Wed, 11 May 2011 02:01:30 +0000 Subject: [PATCH] AI's that do not name themselves after 20 seconds will default to their starting name. Added a direction finding algorithm for target, get_dir_to(). Mostly useful for positioning sprites in relation to a target. Such as energy beams, lines, and so on. Changes to ninjas. Fixed a bunch of bugs and finished content. It is now possible to drag people with you when phase jaunting/shifting. Jaunting/shifting should also kill livestock, huggers, and damage mechs. Renamed /obj/spell path to obj/proc_holder/spell in order to have a generic proc_holder category. For now it only works for the AI but can be expanded to other mobs. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1566 316c924e-a436-60f5-8080-3fe189b3f50e --- code/datums/spell.dm | 37 ++--- code/datums/spells/area_teleport.dm | 10 +- code/datums/spells/conjure.dm | 6 +- code/datums/spells/emplosion.dm | 4 +- code/datums/spells/ethereal_jaunt.dm | 4 +- code/datums/spells/explosion.dm | 4 +- code/datums/spells/genetic.dm | 4 +- code/datums/spells/inflict_handler.dm | 4 +- code/datums/spells/knock.dm | 4 +- code/datums/spells/mind_transfer.dm | 4 +- code/datums/spells/projectile.dm | 12 +- code/datums/spells/trigger.dm | 12 +- code/datums/spells/turf_teleport.dm | 4 +- code/datums/spells/wizard.dm | 42 +++--- code/defines/mob/mob.dm | 6 +- code/defines/procs/helpers.dm | 47 +++++-- code/game/gamemodes/extra/ninja_abilities.dm | 130 ++++++++++++------ code/game/gamemodes/extra/ninja_equipment.dm | 107 +++++++++----- code/game/gamemodes/extra/space_ninja.dm | 112 ++++++++++++--- code/game/gamemodes/wizard/wizard.dm | 32 ++--- code/modules/admin/admin_verbs.dm | 2 +- code/modules/mob/living/carbon/human/death.dm | 1 + code/modules/mob/living/carbon/human/human.dm | 10 +- code/modules/mob/living/silicon/ai/ai.dm | 7 + code/modules/mob/mob.dm | 8 +- config/names/ninjaname.txt | 3 +- config/names/ninjatitle.txt | 3 +- icons/obj/projectiles.dmi | Bin 12964 -> 14643 bytes icons/obj/wizard.dmi | Bin 6112 -> 6641 bytes 29 files changed, 409 insertions(+), 210 deletions(-) diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 37571f35e44..251e401a957 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -1,6 +1,9 @@ -var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now +/obj/proc_holder + var/panel = "Debug"//What panel the proc holder needs to go on. -/obj/spell +var/list/spells = typesof(/obj/proc_holder/spell) //needed for the badmin verb for now + +/obj/proc_holder/spell name = "Spell" desc = "A wizard spell" density = 0 @@ -28,7 +31,7 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now var/smoke_spread = 0 //1 - harmless, 2 - harmful var/smoke_amt = 0 //cropped at 10 -/obj/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell +/obj/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell if(!(src in usr.spell_list)) usr << "\red You shouldn't have this spell! Something's wrong." @@ -69,7 +72,7 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now return 1 -/obj/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount +/obj/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount switch(invocation_type) if("shout") @@ -81,12 +84,12 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now if("whisper") usr.whisper(invocation) -/obj/spell/New() +/obj/proc_holder/spell/New() ..() charge_counter = charge_max -/obj/spell/Click() +/obj/proc_holder/spell/Click() ..() if(!cast_check()) @@ -94,15 +97,15 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now choose_targets() -/obj/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf +/obj/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf return -/obj/spell/proc/start_recharge() +/obj/proc_holder/spell/proc/start_recharge() while(charge_counter < charge_max) sleep(1) charge_counter++ -/obj/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells +/obj/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells before_cast(targets) invocation() spawn(0) @@ -111,7 +114,7 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now cast(targets) after_cast(targets) -/obj/spell/proc/before_cast(list/targets) +/obj/proc_holder/spell/proc/before_cast(list/targets) if(overlay) for(var/atom/target in targets) var/location @@ -127,7 +130,7 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now spawn(overlay_lifespan) del(spell) -/obj/spell/proc/after_cast(list/targets) +/obj/proc_holder/spell/proc/after_cast(list/targets) for(var/atom/target in targets) var/location if(istype(target,/mob)) @@ -150,10 +153,10 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is smoke.start() -/obj/spell/proc/cast(list/targets) +/obj/proc_holder/spell/proc/cast(list/targets) return -/obj/spell/proc/revert_cast() //resets recharge or readds a charge +/obj/proc_holder/spell/proc/revert_cast() //resets recharge or readds a charge switch(charge_type) if("recharge") charge_counter = charge_max @@ -163,15 +166,15 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now return -/obj/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob +/obj/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast var/include_user = 0 //if it includes usr in the target list -/obj/spell/aoe_turf //affects all turfs in view or range (depends) +/obj/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends) var/inner_radius = -1 //for all your ring spell needs -/obj/spell/targeted/choose_targets(mob/user = usr) +/obj/proc_holder/spell/targeted/choose_targets(mob/user = usr) var/list/targets = list() switch(selection_type) @@ -239,7 +242,7 @@ var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now return -/obj/spell/aoe_turf/choose_targets(mob/user = usr) +/obj/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr) var/list/targets = list() switch(selection_type) diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index 138a02ed5bc..cda227aa7a8 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -1,11 +1,11 @@ -/obj/spell/targeted/area_teleport +/obj/proc_holder/spell/targeted/area_teleport name = "Area teleport" desc = "This spell teleports you to a type of area of your selection." var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list var/invocation_area = 1 //if the invocation appends the selected area -/obj/spell/targeted/area_teleport/perform(list/targets, recharge = 1) +/obj/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1) var/thearea = before_cast(targets) if(!thearea || !cast_check(1)) revert_cast() @@ -17,7 +17,7 @@ cast(targets,thearea) after_cast(targets) -/obj/spell/targeted/area_teleport/before_cast(list/targets) +/obj/proc_holder/spell/targeted/area_teleport/before_cast(list/targets) var/A = null if(!randomise_selection) @@ -29,7 +29,7 @@ return thearea -/obj/spell/targeted/area_teleport/cast(list/targets,area/thearea) +/obj/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea) for(var/mob/target in targets) var/list/L = list() for(var/turf/T in get_area_turfs(thearea.type)) @@ -46,7 +46,7 @@ return -/obj/spell/targeted/area_teleport/invocation(area/chosenarea = null) +/obj/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null) if(!invocation_area || !chosenarea) ..() else diff --git a/code/datums/spells/conjure.dm b/code/datums/spells/conjure.dm index 731521e4c6b..ce3fb01fbf0 100644 --- a/code/datums/spells/conjure.dm +++ b/code/datums/spells/conjure.dm @@ -1,4 +1,4 @@ -/obj/spell/aoe_turf/conjure +/obj/proc_holder/spell/aoe_turf/conjure name = "Conjure" desc = "This spell conjures objs of the specified types in range." @@ -9,7 +9,7 @@ var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point /* -/obj/spell/conjure +/obj/proc_holder/spell/conjure name = "Summon Bigger Carp" desc = "This spell conjures an elite carp." @@ -25,7 +25,7 @@ var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point */ -/obj/spell/aoe_turf/conjure/cast(list/targets) +/obj/proc_holder/spell/aoe_turf/conjure/cast(list/targets) for(var/turf/T in targets) if(T.density && !summon_ignore_density) diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm index 1d358865caa..794df4f78d7 100644 --- a/code/datums/spells/emplosion.dm +++ b/code/datums/spells/emplosion.dm @@ -1,11 +1,11 @@ -/obj/spell/targeted/emplosion +/obj/proc_holder/spell/targeted/emplosion name = "Emplosion" desc = "This spell emplodes an area." var/emp_heavy = 2 var/emp_light = 3 -/obj/spell/targeted/emplosion/cast(list/targets) +/obj/proc_holder/spell/targeted/emplosion/cast(list/targets) for(var/mob/target in targets) empulse(target.loc, emp_heavy, emp_light) diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 1a5c47370a9..9d543f69d0c 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/ethereal_jaunt +/obj/proc_holder/spell/targeted/ethereal_jaunt name = "Ethereal Jaunt" desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." @@ -12,7 +12,7 @@ var/jaunt_duration = 50 //in deciseconds -/obj/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded +/obj/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded for(var/mob/target in targets) spawn(0) var/mobloc = get_turf(target.loc) diff --git a/code/datums/spells/explosion.dm b/code/datums/spells/explosion.dm index 96e02e6899a..a6d20291f25 100644 --- a/code/datums/spells/explosion.dm +++ b/code/datums/spells/explosion.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/explosion +/obj/proc_holder/spell/targeted/explosion name = "Explosion" desc = "This spell explodes an area." @@ -7,7 +7,7 @@ var/ex_light = 3 var/ex_flash = 4 -/obj/spell/targeted/explosion/cast(list/targets) +/obj/proc_holder/spell/targeted/explosion/cast(list/targets) for(var/mob/target in targets) explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm index 394c4797c04..94950fcc66d 100644 --- a/code/datums/spells/genetic.dm +++ b/code/datums/spells/genetic.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/genetic +/obj/proc_holder/spell/targeted/genetic name = "Genetic" desc = "This spell inflicts a set of mutations and disabilities upon the target." @@ -22,7 +22,7 @@ 6th bit - fat */ -/obj/spell/targeted/genetic/cast(list/targets) +/obj/proc_holder/spell/targeted/genetic/cast(list/targets) for(var/mob/target in targets) target.mutations |= mutations diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm index 072e3720832..e2e5e0cf1cc 100644 --- a/code/datums/spells/inflict_handler.dm +++ b/code/datums/spells/inflict_handler.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/inflict_handler +/obj/proc_holder/spell/targeted/inflict_handler name = "Inflict Handler" desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target." @@ -16,7 +16,7 @@ var/destroys = "none" //can be "none", "gib" or "disintegrate" -/obj/spell/targeted/inflict_handler/cast(list/targets) +/obj/proc_holder/spell/targeted/inflict_handler/cast(list/targets) for(var/mob/living/target in targets) switch(destroys) diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm index dafa286f919..b1da996e174 100644 --- a/code/datums/spells/knock.dm +++ b/code/datums/spells/knock.dm @@ -1,4 +1,4 @@ -/obj/spell/aoe_turf/knock +/obj/proc_holder/spell/aoe_turf/knock name = "Knock" desc = "This spell opens nearby doors and does not require wizard garb." @@ -9,7 +9,7 @@ invocation_type = "whisper" range = 3 -/obj/spell/aoe_turf/knock/cast(list/targets) +/obj/proc_holder/spell/aoe_turf/knock/cast(list/targets) for(var/turf/T in targets) for(var/obj/machinery/door/door in T.contents) spawn(1) diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm index 6f175562211..93369b568cb 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/datums/spells/mind_transfer.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/mind_transfer +/obj/proc_holder/spell/targeted/mind_transfer name = "Mind Transfer" desc = "This spell allows the user to switch bodies with a target." @@ -17,7 +17,7 @@ var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell -/obj/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded +/obj/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded if(!targets.len) user << "No mind found" return diff --git a/code/datums/spells/projectile.dm b/code/datums/spells/projectile.dm index 1f6fd42800d..efcfca2f3c9 100644 --- a/code/datums/spells/projectile.dm +++ b/code/datums/spells/projectile.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/projectile +/obj/proc_holder/spell/targeted/projectile name = "Projectile" desc = "This spell summons projectiles which try to hit the targets." @@ -11,7 +11,7 @@ var/proj_trail_icon = 'wizard.dmi' var/proj_trail_icon_state = "trail" - var/proj_type = "/obj/spell/targeted" //IMPORTANT use only subtypes of this + var/proj_type = "/obj/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle var/proj_homing = 1 //if it follows the target @@ -21,16 +21,16 @@ var/proj_lifespan = 15 //in deciseconds * proj_step_delay var/proj_step_delay = 1 //lower = faster -/obj/spell/targeted/projectile/cast(list/targets, mob/user = usr) +/obj/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) for(var/mob/target in targets) spawn(0) - var/obj/spell/targeted/projectile + var/obj/proc_holder/spell/targeted/projectile if(istext(proj_type)) var/projectile_type = text2path(proj_type) projectile = new projectile_type(user) - if(istype(proj_type,/obj/spell)) - projectile = new /obj/spell/targeted/trigger(user) + if(istype(proj_type,/obj/proc_holder/spell)) + projectile = new /obj/proc_holder/spell/targeted/trigger(user) projectile:linked_spells += proj_type projectile.icon = proj_icon projectile.icon_state = proj_icon_state diff --git a/code/datums/spells/trigger.dm b/code/datums/spells/trigger.dm index 6aed5cb2a56..232e2f5603f 100644 --- a/code/datums/spells/trigger.dm +++ b/code/datums/spells/trigger.dm @@ -1,28 +1,28 @@ -/obj/spell/targeted/trigger +/obj/proc_holder/spell/targeted/trigger name = "Trigger" desc = "This spell triggers another spell or a few." var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks -/obj/spell/targeted/trigger/New() +/obj/proc_holder/spell/targeted/trigger/New() ..() for(var/spell in starting_spells) var/spell_to_add = text2path(spell) new spell_to_add(src) //should result in adding to contents, needs testing -/obj/spell/targeted/trigger/Del() +/obj/proc_holder/spell/targeted/trigger/Del() for(var/spell in contents) del(spell) ..() -/obj/spell/targeted/trigger/cast(list/targets) +/obj/proc_holder/spell/targeted/trigger/cast(list/targets) for(var/mob/target in targets) - for(var/obj/spell/spell in contents) + for(var/obj/proc_holder/spell/spell in contents) spell.perform(list(target),0) - for(var/obj/spell/spell in linked_spells) + for(var/obj/proc_holder/spell/spell in linked_spells) spell.perform(list(target),0) return \ No newline at end of file diff --git a/code/datums/spells/turf_teleport.dm b/code/datums/spells/turf_teleport.dm index 49d3d6a5952..bfa6ddd5d93 100644 --- a/code/datums/spells/turf_teleport.dm +++ b/code/datums/spells/turf_teleport.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/turf_teleport +/obj/proc_holder/spell/targeted/turf_teleport name = "Turf Teleport" desc = "This spell teleports the target to the turf in range." @@ -8,7 +8,7 @@ var/include_space = 0 //whether it includes space tiles in possible teleport locations var/include_dense = 0 //whether it includes dense tiles in possible teleport locations -/obj/spell/targeted/turf_teleport/cast(list/targets) +/obj/proc_holder/spell/targeted/turf_teleport/cast(list/targets) for(var/mob/target in targets) var/list/turfs = new/list() for(var/turf/T in range(target,outer_tele_radius)) diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index ec504dac74c..cbf223e2ee0 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -1,4 +1,4 @@ -/obj/spell/targeted/projectile/magic_missile +/obj/proc_holder/spell/targeted/projectile/magic_missile name = "Magic Missile" desc = "This spell fires several, slow moving, magic projectiles at nearby targets." @@ -14,7 +14,7 @@ proj_icon_state = "magicm" proj_name = "a magic missile" proj_lingering = 1 - proj_type = "/obj/spell/targeted/inflict_handler/magic_missile" + proj_type = "/obj/proc_holder/spell/targeted/inflict_handler/magic_missile" proj_lifespan = 20 proj_step_delay = 5 @@ -23,11 +23,11 @@ proj_trail_lifespan = 5 proj_trail_icon_state = "magicmd" -/obj/spell/targeted/inflict_handler/magic_missile +/obj/proc_holder/spell/targeted/inflict_handler/magic_missile amt_weaken = 5 amt_dam_fire = 10 -/obj/spell/targeted/genetic/mutate +/obj/proc_holder/spell/targeted/genetic/mutate name = "Mutate" desc = "This spell causes you to turn into a hulk and gain telekinesis for a short while." @@ -43,7 +43,7 @@ mutations = 9 duration = 300 -/obj/spell/targeted/inflict_handler/disintegrate +/obj/proc_holder/spell/targeted/inflict_handler/disintegrate name = "Disintegrate" desc = "This spell instantly kills somebody adjacent to you with the vilest of magick." @@ -59,7 +59,7 @@ sparks_spread = 1 sparks_amt = 4 -/obj/spell/targeted/smoke +/obj/proc_holder/spell/targeted/smoke name = "Smoke" desc = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." @@ -74,7 +74,7 @@ smoke_spread = 2 smoke_amt = 10 -/obj/spell/targeted/emplosion/disable_tech +/obj/proc_holder/spell/targeted/emplosion/disable_tech name = "Disable Tech" desc = "This spell disables all weapons, cameras and most other technology in range." charge_max = 400 @@ -87,7 +87,7 @@ emp_heavy = 5 emp_light = 7 -/obj/spell/targeted/turf_teleport/blink +/obj/proc_holder/spell/targeted/turf_teleport/blink name = "Blink" desc = "This spell randomly teleports you a short distance." @@ -105,7 +105,7 @@ inner_tele_radius = 0 outer_tele_radius = 6 -/obj/spell/targeted/area_teleport/teleport +/obj/proc_holder/spell/targeted/area_teleport/teleport name = "Teleport" desc = "This spell teleports you to a type of area of your selection." @@ -120,7 +120,7 @@ smoke_spread = 1 smoke_amt = 5 -/obj/spell/aoe_turf/conjure/forcewall +/obj/proc_holder/spell/aoe_turf/conjure/forcewall name = "Forcewall" desc = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb." @@ -134,7 +134,7 @@ summon_type = list("/obj/forcefield") summon_lifespan = 300 -/obj/spell/aoe_turf/conjure/carp +/obj/proc_holder/spell/aoe_turf/conjure/carp name = "Summon Bigger Carp" desc = "This spell conjures an elite carp." @@ -147,7 +147,7 @@ summon_type = list("/obj/livestock/spesscarp/elite") -/obj/spell/targeted/trigger/blind +/obj/proc_holder/spell/targeted/trigger/blind name = "Blind" desc = "This spell temporarily blinds a single person and does not require wizard garb." @@ -158,17 +158,17 @@ invocation_type = "whisper" message = "\blue Your eyes cry out in pain!" - starting_spells = list("/obj/spell/targeted/inflict_handler/blind","/obj/spell/targeted/genetic/blind") + starting_spells = list("/obj/proc_holder/spell/targeted/inflict_handler/blind","/obj/proc_holder/spell/targeted/genetic/blind") -/obj/spell/targeted/inflict_handler/blind +/obj/proc_holder/spell/targeted/inflict_handler/blind amt_eye_blind = 10 amt_eye_blurry = 20 -/obj/spell/targeted/genetic/blind +/obj/proc_holder/spell/targeted/genetic/blind disabilities = 1 duration = 300 -/obj/spell/targeted/projectile/fireball +/obj/proc_holder/spell/targeted/projectile/fireball name = "Fireball" desc = "This spell fires a fireball at a target and does not require wizard garb." @@ -181,19 +181,19 @@ proj_icon_state = "fireball" proj_name = "a fireball" proj_lingering = 1 - proj_type = "/obj/spell/targeted/trigger/fireball" + proj_type = "/obj/proc_holder/spell/targeted/trigger/fireball" proj_lifespan = 200 proj_step_delay = 1 -/obj/spell/targeted/trigger/fireball - starting_spells = list("/obj/spell/targeted/inflict_handler/fireball","/obj/spell/targeted/explosion/fireball") +/obj/proc_holder/spell/targeted/trigger/fireball + starting_spells = list("/obj/proc_holder/spell/targeted/inflict_handler/fireball","/obj/proc_holder/spell/targeted/explosion/fireball") -/obj/spell/targeted/inflict_handler/fireball +/obj/proc_holder/spell/targeted/inflict_handler/fireball amt_dam_brute = 20 amt_dam_fire = 25 -/obj/spell/targeted/explosion/fireball +/obj/proc_holder/spell/targeted/explosion/fireball ex_severe = -1 ex_heavy = -1 ex_light = 2 diff --git a/code/defines/mob/mob.dm b/code/defines/mob/mob.dm index 16b5039c4ea..282753e90ef 100644 --- a/code/defines/mob/mob.dm +++ b/code/defines/mob/mob.dm @@ -162,8 +162,12 @@ var/voice_message = null // When you are not understood by others (replaced with just screeches, hisses, chimpers etc.) var/say_message = null // When you are understood by others. Currently only used by aliens and monkeys in their say_quote procs +//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 only displays for the AI. + //Also unlike the spell list, this would only store the object in contents, not an object in itself. + //Wizard mode, but can be used in other modes thanks to the brand new "Give Spell" badmin button - var/obj/spell/list/spell_list = list() + var/obj/proc_holder/spell/list/spell_list = list() //Monkey/infected mode var/list/resistances = list() diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm index 8b425c6f886..5f1bed407dd 100644 --- a/code/defines/procs/helpers.dm +++ b/code/defines/procs/helpers.dm @@ -365,6 +365,22 @@ if(degree < 315) return WEST return NORTH|WEST +//Returns direction that the mob or whomever should be facing in relation to the target. +//This proc does not grant absolute direction and is mostly useful for 8dir sprite positioning. +//I personally used it with getline() to great effect. +/proc/get_dir_to(var/turf/start as turf,var/turf/end as turf)//N + var/xdiff = start.x - end.x//The sign is important. + var/ydiff = start.y - end.y + + var/direction_x = xdiff<1 ? 4:8//East - west + var/direction_y = ydiff<1 ? 1:2//North - south + var/direction_xy = xdiff==0 ? -4:0//If x is the same, subtract 4. + var/direction_yx = ydiff==0 ? -1:0//If y is the same, subtract 1. + var/direction_f = direction_x+direction_y+direction_xy+direction_yx//Finally direction tally. + direction_f = direction_f==0 ? 1:direction_f//If direction is 0(same spot), return north. Otherwise, direction. + + return direction_f + /proc/angle2text(var/degree) return dir2text(angle2dir(degree)) @@ -519,7 +535,11 @@ /proc/ainame(var/mob/M as mob) var/randomname = M.name + var/time_passed = world.time//Pretty basic but it'll do. It's still possible to bypass this by return ainame(). var/newname = input(M,"You are the AI. Would you like to change your name to something else?", "Name change",randomname) + if((world.time-time_passed)>200)//If more than 20 game seconds passed. + M << "You took too long to decide. Default name selected." + return if (length(newname) == 0) newname = randomname @@ -885,22 +905,23 @@ proc/GaussRand(var/sigma) proc/GaussRandRound(var/sigma,var/roundto) return round(GaussRand(sigma),roundto) -proc/anim(a,b,c,d,e) -//a is location, b is animation icon, c is the layer, d is the flick animation, e is sleep time (optional). -//Make sure that c actually has a layer or the game will run time error. - var/atom/movable/overlay/animation = new(a) - animation.icon = b - animation.icon_state = "blank" - animation.layer = c:layer+1//++ won't work right here. - animation.master = a - flick(d, animation) - if(e) - sleep(e) +proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num) +//This proc throws up either an icon or an animation for a specified amount of time. +//The variables should be apparent enough. + var/atom/movable/overlay/animation = new(location) + if(direction) + animation.dir = direction + animation.icon = a_icon + animation.layer = target:layer+1 + if(a_icon_state) + animation.icon_state = a_icon_state else - sleep(15) + animation.icon_state = "blank" + animation.master = target + flick(flick_anim, animation) + sleep(max(sleeptime, 15)) del(animation) - //returns list element or null. Should prevent "index out of bounds" error. proc/listgetindex(var/list/list,index) if(istype(list) && list.len) diff --git a/code/game/gamemodes/extra/ninja_abilities.dm b/code/game/gamemodes/extra/ninja_abilities.dm index 1001b8d0781..a401a0d9957 100644 --- a/code/game/gamemodes/extra/ninja_abilities.dm +++ b/code/game/gamemodes/extra/ninja_abilities.dm @@ -13,13 +13,13 @@ In the case that they are not, I imagine the game will run-time error like crazy */ //Cooldown ticks off each second based on the suit recharge proc, in seconds. Default of 1 seconds. Some abilities have no cool down. -/mob/proc/ninjacost(var/C as num,var/X as num) +/mob/proc/ninjacost(var/C = 0,var/X = 0) var/mob/living/carbon/human/U = src var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - if(U.stat||U.incorporeal_move) - U << "\red You must be conscious and solid to do this." + if(U.stat||U.incorporeal_move&&X!=3)//Will not return if user is using an adrenaline booster since you can use them when stat==1. + U << "\red You must be conscious and solid to do this."//It's not a problem of stat==2 since the ninja will explode anyway if they die. return 1 - else if(C&&S.cell.chargeteleportation failed." @@ -385,7 +433,7 @@ Allows to gib up to five squares in a straight line. Seriously.*/ /mob/proc/ninjamirage() set name = "Spider Mirage" set desc = "Utilizes the internal VOID-shift device to create decoys and teleport behind a random target." - set category = "Ninja" + set category = "Ninja Ability" if(!ninjacost())//Simply checks for stat. var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit @@ -428,14 +476,14 @@ Allows to gib up to five squares in a straight line. Seriously.*/ var/turf/picked = locate(locx,locy,mobloc.z) spawn(0) playsound(loc, "sparks", 50, 1) - anim(mobloc,'mob.dmi',src,"phaseout") + anim(mobloc,src,'mob.dmi',,"phaseout") spawn(0) var/limit = 4 for(var/turf/T in oview(5)) if(prob(20)) spawn(0) - anim(T,'mob.dmi',src,"phasein") + anim(T,src,'mob.dmi',,"phasein") limit-- if(limit<=0) break @@ -446,7 +494,7 @@ Allows to gib up to five squares in a straight line. Seriously.*/ S.spark_system.start() playsound(loc, 'Deconstruct.ogg', 50, 1) playsound(loc, "sparks", 50, 1) - anim(loc,'mob.dmi',src,"phasein") + anim(loc,src,'mob.dmi',,"phasein") S.coold = 1 else src << "\red The VOID-shift device is malfunctioning, teleportation failed." diff --git a/code/game/gamemodes/extra/ninja_equipment.dm b/code/game/gamemodes/extra/ninja_equipment.dm index 39cdbe0b3b4..c0697dfa804 100644 --- a/code/game/gamemodes/extra/ninja_equipment.dm +++ b/code/game/gamemodes/extra/ninja_equipment.dm @@ -34,6 +34,7 @@ ________________________________________________________________________________ /obj/item/clothing/suit/space/space_ninja/proc/killai(var/mob/living/silicon/ai/A as mob) A << "\red Self-destruct protocol dete-- *bzzzzz*" + A << browse(null, "window=hack spideros") A.death()//Kill A.ghostize()//Turn into ghost del(AI) @@ -72,19 +73,23 @@ ________________________________________________________________________________ U.bruteloss += 1 A = 200 cell.charge-=A + if(U.stat)//If the ninja falls down, + active=0 if(cell.charge<0) if(kamikaze) U.say("I DIE TO LIVE AGAIN!") + U << browse(null, "window=spideros")//Just in case. U.death() return cell.charge=0 active=0 sleep(10)//Checks every second. + /obj/item/clothing/suit/space/space_ninja/proc/init() set name = "Initialize Suit" set desc = "Initializes the suit for field operation." - set category = "Object" + set category = "Ninja Equip" var/mob/living/carbon/human/U = usr if(U.mind&&U.mind.special_role=="Space Ninja"&&U:wear_suit==src&&!initialize) @@ -170,15 +175,13 @@ ________________________________________________________________________________ /obj/item/clothing/suit/space/space_ninja/proc/deinit() set name = "De-Initialize Suit" set desc = "Begins procedure to remove the suit." - set category = "Object" + set category = "Ninja Equip" if(!initialize) usr << "\red The suit is not initialized." return if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No") return - if(!verbs.Find(/obj/item/clothing/suit/space/space_ninja/proc/spideros))//If the guy engaged kamikaze after clicking on deinit. - return var/mob/living/carbon/human/U = affecting verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit @@ -269,7 +272,8 @@ ________________________________________________________________________________ /obj/item/clothing/suit/space/space_ninja/proc/spideros() set name = "Display SpiderOS" set desc = "Utilize built-in computer system." - set category = "Object" + set category = "Ninja Equip" + //set src in view()//To have it show up after AI gives back control. if(!affecting) return//If no mob is wearing the suit. I almost forgot about this variable. var/mob/living/carbon/human/U = affecting @@ -520,14 +524,14 @@ ________________________________________________________________________________ if("Stealth") if(active) spawn(0) - anim(U.loc,'mob.dmi',U,"uncloak") + anim(U.loc,U,'mob.dmi',,"uncloak") active=0 U << "\blue You are now visible." for(var/mob/O in oviewers(U, null)) O << "[U.name] appears from thin air!" else spawn(0) - anim(U.loc,'mob.dmi',U,"cloak") + anim(U.loc,U,'mob.dmi',,"cloak") active=1 U << "\blue You are now invisible to normal detection." for(var/mob/O in oviewers(U, null)) @@ -566,7 +570,7 @@ ________________________________________________________________________________ P.overlays += image('pda.dmi', "pda-r") if("Unlock Kamikaze") if(input(U)=="Divine Wind") - if( !(U.stat||U.wear_suit!=src||!initialize) ) + if( !(U.stat||U.wear_suit!=src||!initialize||cell.charge<=1) ) U << "\blue Engaging mode...\n\blackCODE NAME: \red KAMIKAZE" verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros sleep(40) @@ -663,39 +667,74 @@ ________________________________________________________________________________ U << browse(null, "window=spideros") return if(confirm == "Yes") - if(A.laws_object.zeroth) - A << "\red WARNING: \black purge procedure detected. \n Now hacking host..." - A.control_disabled = 0 + if(A.laws_object.zeroth)//Gives a few seconds to re-upload the AI somewhere before it takes full control. + A << "\red WARNING: \black purge procedure detected. \nNow hacking host..." U << "\red WARNING: HACKING ATT--TEMPT IN PR0GRESsS!" spideros = 0 unlock = 0 - active = 0 - control = 0 - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros - A.verbs += /mob/living/silicon/ai/proc/ninja_spideros - A.verbs += /mob/living/silicon/ai/proc/ninja_return_control U << browse(null, "window=spideros") + spawn(40)//Unlimited window spawn works! + if(AI==A) + A << "Disconnecting neural interface..." + U << "\red WARNING: PRO0GRE--S 2&3%" + verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit + verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros + spawn(40) + if(AI==A) + A << "Shutting down external protocol..." + U << "\red WARNING: PPPFRRROGrESS 677^%" + active = 0 + spawn(40) + if(AI==A) + A << "Connecting to kernel..." + U << "\red WARNING: ER-RR04" + A.control_disabled = 0 + spawn(40) + A << "Connection established and secured. Menu updated." + U << "\red WARNING: #%@!!WEL4P54@" + control = 0 + var/obj/proc_holder/ai_return_control/A_C = new(A) + var/obj/proc_holder/ai_hack_ninja/B_C = new(A) + A.proc_holder_list += A_C + A.proc_holder_list += B_C + else + U << "\blue Hacking attempt disconnected. Resuming normal operation." + verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit + verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros + else + U << "\blue Hacking attempt disconnected. Resuming normal operation." + verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit + verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros + else + U << "\blue Hacking attempt disconnected. Resuming normal operation." return else flush = 1 A.suiciding = 1 A << "Your core files are being purged! This is the end..." + spawn(0) + spideros()//To refresh the screen and let this finish. while (A.stat != 2) A.oxyloss += 2 A.updatehealth() sleep(10) killai(A) + flush = 0 if("Wireless AI") var/mob/living/silicon/ai/A = locate(href_list["target"]) A.control_disabled = !A.control_disabled A << "AI wireless has been [A.control_disabled ? "disabled" : "enabled"]." spideros()//Refreshes the screen by calling it again (which replaces current screen with new screen). + else//If they are not in control. var/mob/living/silicon/ai/AI = usr - //While AI has control, the person can't take off the suit so checking here would be moot. + if(isnull(src))//If they AI dies/suit destroyed. + AI << browse(null, "window=hack spideros") + return + + var/obj/proc_holder/ai_hack_ninja/ninja_spideros = locate() in AI//What is the object granting access to proc? Find it. switch(href_list["choice"]) if("Close") @@ -706,13 +745,13 @@ ________________________________________________________________________________ if(spideros<=9) spideros=0 else - spideros = round(spideros/10)//Best way to do this, flooring to nearest integer. As an example, another way of doing it is attached below: - if("Shock") + spideros = round(spideros/10) + if("Shock")//DEBUG TEST var/damage = min(cell.charge, rand(50,150))//Uses either the current energy left over or between 50 and 150. - cell.charge -= damage if(damage>1)//So they don't spam it when energy is a factor. spark_system.start()//SPARKS THERE SHALL BE SPARKS - U.electrocute_act(damage, src, 0.1) + U.electrocute_act(damage, src,0.1,1)//The last argument is a safety for the human proc that checks for gloves. + cell.charge -= damage else AI << "\red ERROR: \black Not enough energy remaining." if("0")//Menus are numbers, see note above. 0 is the hub. @@ -734,7 +773,7 @@ ________________________________________________________________________________ return if(isnull(P)||P.toff)//So it doesn't freak out if the object no-longer exists. AI << "\red Error: unable to deliver message." - AI.ninja_spideros() + ninja_spideros.Click() return P.tnote += "← From [AI]:
[t]
"//Oh ai, u so silly if (!P.silent) @@ -779,10 +818,10 @@ ________________________________________________________________________________ U << "You feel a tiny prick and a sudden rush of liquid in to your veins." if("Radium") if((reagents.get_reagent_amount("radium"))<=60)//Special case. If there are only 60 radium units left. - AI << "\red Error: the suit cannot perform this function. Out of spaceacillin." + AI << "\red Error: the suit cannot perform this function. Out of radium." else reagents.reaction(U, 2) - reagents.trans_id_to(U, "spaceacillin", transfera) + reagents.trans_id_to(U, "radium", transfera) AI << "Injecting..." U << "You feel a tiny prick and a sudden rush of liquid in to your veins." if("Nutriment") @@ -793,7 +832,7 @@ ________________________________________________________________________________ reagents.trans_id_to(U, "nutriment", 5) AI << "Injecting..." U << "You feel a tiny prick and a sudden rush of substance in to your veins." - AI.ninja_spideros()//Calls spideros for AI. + ninja_spideros.Click()//Calls spideros for AI. return /obj/item/clothing/suit/space/space_ninja/examine() @@ -819,7 +858,7 @@ ________________________________________________________________________________ /obj/item/clothing/gloves/space_ninja/proc/toggled() set name = "Toggle Interaction" set desc = "Toggles special interaction on or off." - set category = "Object" + set category = "Ninja Equip" if(!candrain) candrain=1 usr << "You enable special interaction." @@ -832,7 +871,7 @@ ________________________________________________________________________________ /obj/item/clothing/gloves/space_ninja/proc/drain_wire() set name = "Drain From Wire" set desc = "Drain energy directly from an exposed wire." - set category = "Object" + set category = "Ninja Equip" var/obj/cable/attached var/mob/living/carbon/human/U = usr @@ -1089,7 +1128,7 @@ ________________________________________________________________________________ /obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev() set name = "Toggle Voice" set desc = "Toggles the voice synthesizer on or off." - set category = "Object" + set category = "Ninja Equip" var/vchange = (alert("Would you like to synthesize a new name or turn off the voice synthesizer?",,"New Name","Turn Off")) if(vchange=="New Name") var/chance = rand(1,100) @@ -1132,7 +1171,7 @@ ________________________________________________________________________________ /obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm() set name = "Switch Mode" set desc = "Switches between Night Vision, Meson, or Thermal vision modes." - set category = "Object" + set category = "Ninja Equip" //Have to reset these manually since life.dm is retarded like that. Go figure. switch(mode) if(1) @@ -1299,7 +1338,7 @@ The sprite for the net is kind of ugly but I couldn't come up with a better one. check-- sleep(10) - if(isnull(M))//If mob is gone. + if(isnull(M)||M.loc!=loc)//If mob is gone or not at the location. if(!isnull(master))//As long as they still exist. master << "\red ERROR: \black unable to locate [affecting]. Procedure terminated." del(src)//Get rid of the net. @@ -1309,9 +1348,11 @@ The sprite for the net is kind of ugly but I couldn't come up with a better one. //No need to check for countdown here since while() broke, it's implicit that it finished. spawn(0) playsound(M.loc, 'sparks4.ogg', 50, 1) - anim(M.loc,'mob.dmi',M,"phaseout") + anim(M.loc,M,'mob.dmi',,"phaseout") M.loc = pick(prisonwarp)//Throw mob in prison. + invisibility = 101//Make the net invisible so all the animations can play out. + health = INFINITY//Make the net invincible so that an explosion/something else won't kill it while, while() is running. spawn(0) var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread() @@ -1319,7 +1360,7 @@ The sprite for the net is kind of ugly but I couldn't come up with a better one. spark_system.start() playsound(M.loc, 'Deconstruct.ogg', 50, 1) playsound(M.loc, 'sparks2.ogg', 50, 1) - anim(M.loc,'mob.dmi',M,"phasein") + anim(M.loc,M,'mob.dmi',,"phasein") del(src)//Wait for everything to finish, delete the net. Else it will stop everything once net is deleted, including the spawn(0). for(var/mob/O in viewers(src, 3)) diff --git a/code/game/gamemodes/extra/space_ninja.dm b/code/game/gamemodes/extra/space_ninja.dm index 85e654a1ba8..96cf70f30b6 100644 --- a/code/game/gamemodes/extra/space_ninja.dm +++ b/code/game/gamemodes/extra/space_ninja.dm @@ -95,25 +95,43 @@ mob/proc/create_ninja() //AI COUNTER HACKING=================================== -/mob/living/silicon/ai/proc/ninja_spideros() - set name = "Hack SpiderOS" - set desc = "Hack directly into the Black Widow(tm) neuro-interface." - set category = "AI Commands" +//I've tried a lot of stuff but adding verbs to the AI while inside an object, inside another object, did not want to work properly. +//This the best work-around I could come up with. Uses objects to then display to panel, based on the object spell system. +/obj/proc_holder/ai_hack_ninja//Generic proc holder to make sure the two verbs below work propely. + name = "Hack SpiderOS" + desc = "Hack directly into the Black Widow(tm) neuro-interface." + panel = "AI Hacking" + density = 0 + opacity = 0 - loc.loc:hack_spideros()//ninjasuit:hack_spideros() +/obj/proc_holder/ai_hack_ninja/Click()//When you click on it. + var/obj/item/clothing/suit/space/space_ninja/S = loc.loc//This is so stupid but makes sure certain things work. AI.SUIT + S.hack_spideros() + return -/mob/living/silicon/ai/proc/ninja_return_control() - set name = "Relinquish Control" - set desc = "Return control to the user." - set category = "AI Commands" +/obj/proc_holder/ai_return_control + name = "Relinquish Control" + desc = "Return control to the user." + panel = "AI Hacking" + density = 0 + opacity = 0 - src << browse(null, "window=hack spideros")//Close window - loc:control = 0//Return control - loc:affecting:verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit//Add back verbs - loc:affecting:verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros - verbs -= /mob/living/silicon/ai/proc/ninja_spideros - verbs -= /mob/living/silicon/ai/proc/ninja_return_control - loc:affecting << "UPDATE: [real_name] has seized hacking attempt. All systems clear." +/obj/proc_holder/ai_return_control/Click() + var/mob/living/silicon/ai/A = loc + var/obj/item/clothing/suit/space/space_ninja/S = A.loc + A << browse(null, "window=hack spideros")//Close window + S.control = 1//Return control + A << "You have seized your hacking attempt. [S.affecting] has regained control." + S.affecting << "UPDATE: [A.real_name] has seized hacking attempt. All systems clear." + var/obj/proc_holder/ai_return_control/A_C = locate() in A + var/obj/proc_holder/ai_hack_ninja/B_C = locate() in A + A.proc_holder_list -= A_C + A.proc_holder_list -= B_C + S.verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit + S.verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros + del(A_C)//First. + del(B_C)//Second, to keep the proc going. + return /obj/item/clothing/suit/space/space_ninja/proc/hack_spideros() @@ -144,7 +162,6 @@ mob/proc/create_ninja() dat += "
  • Medical Screen
  • " dat += "
  • Atmos Scan
  • " dat += "
  • Messenger
  • " - dat += "
  • Other
  • " dat += "" if(1) dat += "

    Medical Report:

    " @@ -165,7 +182,7 @@ mob/proc/create_ninja() dat += "
  • Inject Dexalin Plus: [reagents.get_reagent_amount("dexalinp")/20] left
  • " dat += "
  • Inject Tricordazine: [reagents.get_reagent_amount("tricordrazine")/20] left
  • " dat += "
  • Inject Spacelin: [reagents.get_reagent_amount("spaceacillin")/20] left
  • " - dat += "
  • Inject Radium: [(reagents.get_reagent_amount("radium")/20)-60] left
  • "//There is 120 radium at start. -60 for adrenaline boosts. + dat += "
  • Inject Radium: [(reagents.get_reagent_amount("radium")-60)/20] left
  • "//There is 120 radium at start. -60 for adrenaline boosts. dat += "
  • Inject Nutriment: [reagents.get_reagent_amount("nutriment")/5] left
  • "//Special case since it's so freaking potent. dat += "" if(2) @@ -221,8 +238,61 @@ mob/proc/create_ninja() //DEBUG=================================== -//Switches keys with AI stored inside suit. Useful for quickly testing things. +//Apparently you cannot grant verbs to objects within objects. That is, the verbs won't be recognized. +//That object/mob won't be able to grant/remove verbs either. /* +/mob/verb/grant_object_panel() + set name = "Grant AI Ninja Verbs Debug" + set category = "Ninja Debug" + var/obj/proc_holder/ai_return_control/A_C = new(src) + var/obj/proc_holder/ai_hack_ninja/B_C = new(src) + usr:proc_holder_list += A_C + usr:proc_holder_list += B_C + +mob/verb/remove_object_panel() + set name = "Remove AI Ninja Verbs Debug" + set category = "Ninja Debug" + var/obj/proc_holder/ai_return_control/A = locate() in src + var/obj/proc_holder/ai_hack_ninja/B = locate() in src + usr:proc_holder_list -= A + usr:proc_holder_list -= B + del(A)//First. + del(B)//Second, to keep the proc going. + return + +/client/verb/grant_verb_ninja_debug1(var/mob/M in view()) + set name = "Grant AI Ninja Verbs Debug" + set category = "Ninja Debug" + + M.verbs += /mob/living/silicon/ai/verb/ninja_return_control + M.verbs += /mob/living/silicon/ai/verb/ninja_spideros + return + +/client/verb/grant_verb_ninja_debug2(var/mob/living/carbon/human/M in view()) + set name = "Grant Back Ninja Verbs" + set category = "Ninja Debug" + + M.wear_suit.verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit + M.wear_suit.verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros + return + +/obj/proc/grant_verb_ninja_debug3(var/mob/living/silicon/ai/A as mob) + set name = "Grant AI Ninja Verbs" + set category = "null" + set hidden = 1 + A.verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit + A.verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros + return + +/mob/verb/get_dir_to_target(var/mob/M in oview()) + set name = "Get Direction to Target" + set category = "Ninja Debug" + + world << "DIR: [get_dir_to(src.loc,M.loc)]" + return + +//Switches keys with AI stored inside suit. Useful for quickly testing things. + var/ninja_debug_target//Easiest way to do this. The proc below sets this variable to your mob. /mob/verb/possess_mob(var/mob/M in oview()) @@ -264,10 +334,10 @@ var/ninja_debug_target//Easiest way to do this. The proc below sets this variabl spawn(0)//Parallel processing. E.process(src) return -*/ -/* + I made this as a test for a possible ninja ability (or perhaps more) for a certain mob to see hallucinations. The thing here is that these guys have to be coded to do stuff as they are simply images that you can't even click on. +Their movement is also awkward and overlaps. /mob/verb/TestNinjaShadow() set name = "Test Ninja Ability" set category = "Ninja Debug" diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index a2ea312857d..65a1aecf00b 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -175,7 +175,7 @@ wizard_mob.verbs += /client/proc/jaunt wizard_mob.mind.special_verbs += /client/proc/jaunt else - wizard_mob.spell_list += new /obj/spell/targeted/ethereal_jaunt(usr) + wizard_mob.spell_list += new /obj/proc_holder/spell/targeted/ethereal_jaunt(usr) //So zards properly get their items when they are admin-made. del(wizard_mob.wear_suit) @@ -385,7 +385,7 @@ else if(spell_type == "object") var/list/available_spells = list("Magic Missile","Fireball","Disintegrate","Disable Tech","Smoke","Blind","Mind Transfer","Forcewall","Blink","Teleport","Mutate","Ethereal Jaunt","Knock") var/already_knows = 0 - for(var/obj/spell/aspell in usr.spell_list) + for(var/obj/proc_holder/spell/aspell in usr.spell_list) if(available_spells[text2num(href_list["spell_choice"])] == aspell.name) already_knows = 1 src.temp = "You already know that spell." @@ -394,43 +394,43 @@ if(!already_knows) switch(href_list["spell_choice"]) if ("1") - usr.spell_list += new /obj/spell/targeted/projectile/magic_missile(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/projectile/magic_missile(usr) src.temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage." if ("2") - usr.spell_list += new /obj/spell/targeted/projectile/fireball(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/projectile/fireball(usr) src.temp = "This spell fires a fireball at a target and does not require wizard garb. Be careful not to fire it at people that are standing next to you." if ("3") - usr.spell_list += new /obj/spell/targeted/inflict_handler/disintegrate(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/inflict_handler/disintegrate(usr) src.temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown." if ("4") - usr.spell_list += new /obj/spell/targeted/emplosion/disable_tech(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/emplosion/disable_tech(usr) src.temp = "This spell disables all weapons, cameras and most other technology in range." if ("5") - usr.spell_list += new /obj/spell/targeted/smoke(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/smoke(usr) src.temp = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." if ("6") - usr.spell_list += new /obj/spell/targeted/trigger/blind(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/trigger/blind(usr) src.temp = "This spell temporarly blinds a single person and does not require wizard garb." if ("7") - usr.spell_list += new /obj/spell/targeted/mind_transfer(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/mind_transfer(usr) src.temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process." if ("8") - usr.spell_list += new /obj/spell/aoe_turf/conjure/forcewall(usr) + usr.spell_list += new /obj/proc_holder/spell/aoe_turf/conjure/forcewall(usr) src.temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb." if ("9") - usr.spell_list += new /obj/spell/targeted/turf_teleport/blink(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/turf_teleport/blink(usr) src.temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience." if ("10") - usr.spell_list += new /obj/spell/targeted/area_teleport/teleport(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/area_teleport/teleport(usr) src.temp = "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable." if ("11") - usr.spell_list += new /obj/spell/targeted/genetic/mutate(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/genetic/mutate(usr) src.temp = "This spell causes you to turn into a hulk and gain telekinesis for a short while." if ("12") - usr.spell_list += new /obj/spell/targeted/ethereal_jaunt(usr) + usr.spell_list += new /obj/proc_holder/spell/targeted/ethereal_jaunt(usr) src.temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." if ("13") - usr.spell_list += new /obj/spell/aoe_turf/knock(usr) + usr.spell_list += new /obj/proc_holder/spell/aoe_turf/knock(usr) src.temp = "This spell opens nearby doors and does not require wizard garb." if (href_list["spell_choice"] == "14") var/area/wizard_station/A = locate() @@ -660,7 +660,7 @@ M.mind.special_verbs -= /mob/proc/swap M.mind.special_verbs -= /client/proc/blink else if(spell_type == "object") - for(var/obj/spell/spell_to_remove in src.spell_list) + for(var/obj/proc_holder/spell/spell_to_remove in src.spell_list) del(spell_to_remove) /*Checks if the wizard can cast spells. diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index f8a9090d60e..a258e9e19c0 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1409,7 +1409,7 @@ set category = "Fun" set name = "Give Spell" set desc = "Gives a spell to a mob." - var/obj/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") in spells + var/obj/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") in spells T.spell_list += new S /client/proc/make_sound(var/obj/O in world) // -- TLE diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index a1a907cce00..2056d260e34 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -12,6 +12,7 @@ //For ninjas exploding when they die./N if (istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)&&wear_suit:initialize) + src << browse(null, "window=spideros")//Just in case. var/location = loc explosion(location, 1, 2, 3, 4) //src.flags = 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 99a5185eb82..ac5a14f9c50 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -2745,10 +2745,12 @@ It can still be worn/put on as normal. if (istype(id)) return id -/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0) - if(src.gloves) - var/obj/item/clothing/gloves/G = src.gloves - siemens_coeff = G.siemens_coefficient +//Added a safety check in case you want to shock a human mob directly through electrocute_act. +/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/safety = 0) + if(!safety) + if(gloves) + var/obj/item/clothing/gloves/G = src.gloves + siemens_coeff = G.siemens_coefficient return ..(shock_damage,source,siemens_coeff) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 9884d7482b0..af34a3a2f91 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -8,6 +8,9 @@ anchored = 1 canmove = 0 src.loc = loc + + proc_holder_list = new() + if(L) if (istype(L, /datum/ai_laws)) laws_object = L @@ -69,6 +72,10 @@ else stat(null, text("Systems nonfunctional")) + if (proc_holder_list.len)//Generic list for proc_holder objects. + for(var/obj/proc_holder/P in proc_holder_list) + statpanel("[P.panel]","",P) + /mob/living/silicon/ai/proc/ai_alerts() set category = "AI Commands" set name = "Show Alerts" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 88b3796ec32..3c8597a22ae 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1744,12 +1744,12 @@ proc/isobserver(A) var/limit = 2//For only two trailing shadows. for(var/turf/T in getline(mobloc, mob.loc)) spawn(0) - anim(T,'mob.dmi',mob,"shadow") + anim(T,mob,'mob.dmi',,"shadow") limit-- if(limit<=0) break else spawn(0) - anim(mobloc,'mob.dmi',mob,"shadow") + anim(mobloc,mob,'mob.dmi',,"shadow") mob.loc = get_step(mob, direct) mob.dir = direct return @@ -2131,9 +2131,9 @@ note dizziness decrements automatically in the mob's Life() proc. //if (master_controller) // stat(null, "Loop: [master_controller.loop_freq]") - if (src.spell_list.len) + if (spell_list.len) - for(var/obj/spell/S in src.spell_list) + for(var/obj/proc_holder/spell/S in src.spell_list) switch(S.charge_type) if("recharge") statpanel("Spells","[S.charge_counter/10.0]/[S.charge_max/10]",S) diff --git a/config/names/ninjaname.txt b/config/names/ninjaname.txt index 59611610297..b41271dbe10 100644 --- a/config/names/ninjaname.txt +++ b/config/names/ninjaname.txt @@ -40,4 +40,5 @@ Bro Fox Null Raiden -Samurai \ No newline at end of file +Samurai +Eater \ No newline at end of file diff --git a/config/names/ninjatitle.txt b/config/names/ninjatitle.txt index 397dcc0d383..2c7f9e7f73c 100644 --- a/config/names/ninjatitle.txt +++ b/config/names/ninjatitle.txt @@ -42,4 +42,5 @@ Solidus Steel Nickel Silver -Singing \ No newline at end of file +Singing +Snake \ No newline at end of file diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 390b4229dd672ecfcfa48a8db9c447fdfc369fb8..2b7c9a968712c152f8a0ac1a45ba8e744a4bae4e 100644 GIT binary patch literal 14643 zcmaL8byyVP+crE)Bi%@sf;1vs(jW@b(jXv6hjc9>9ZLvE2nf>M9nvA)or=WLjqJXI zzwiCN=X>Ahc>dU9;hvd$X71~}&hxyknGJufs)+Z1>Hz=%c*;t08UO$>1wYTRFu;+I z!+GA|7t&kn%?CM4S96#5P9NSoIskxYdSYyAOeZhlC)?X6I%7<746Ne~BIsW=IykZf z^oS$fi0AR890SnhQP5JXCV0T~BnF?$>vhFvCgxshwy<~Vk$*x`WQMwF^O(h~jgBiy z-kp)(QvVfy*3h10akhnV7yY;V$^yVD0g z%L_^yJ|WD-OsaOfg+u3OG0&dD(z<7-3?sV{2&lp{DJ+djk3(>RP>q}cK+<{!n{ zXbC#~g~4qx`MqnZ86dgG|wKJZ(XIFtC*&}Ys8@7LMZuwM*1 zy3Za;ky8oN8HDAYw>D7jztGzs?gdzVf+ErPfyl`DJ))Tu<=D6iR6|3HC+4-vy_C!0 zkHw02+@rebLi6apbLv0k8X%=-dQ>&=uDyBWE~hE=RVvJ1TUY4zmJh48Svf<~Xx}jt zF)gAUKf8xcL`0Tp=Z+Z`#!iO%C9IzX*OZAVffpJc_OcUr%=8rd{~LVcdd&#SR|KG= z9{TKd9${fGVEMX3EibQBEixiC>TvkPGw1@Vp^mIw$zd~6T)wweSK$Xyvch`+H#(gf zZ0%1P``3*b1se+tzH<|E-=7Oa+U`lYkQ$nrV6P^qw43kH zTD5!g2gNx#2&}R2%Z%?|gad0oQ}{Qg3N?uV!xm5VmZMG_d8EPLW5)oN`w6zGjJNi( zpgII5cL5_C#j4y(nPyn!dLNYt#Nijpe@r<1&V-6sDs*mpxPzl$u(X?TM_*q+h(s z_9z>VxVGv69?sKRL$-2huE*zAoS zlZvKfwWnNa?VNR4Z4OEQ4Jprk{jC&cU5!2Sb~L+{PQll%Yo0tyu zjDwv(-7u|~I{-}02M`pxa2;ZGCmfl6wI&Uic93Cd~Bh8>g>^MRdR3lF@R8=CH z6~E&Pw`DB{9B;_0Yieq42{B4|j=udxI1= zc_Zkl3H#=Rx!yJ*lJI+}>;p7|ALnr48I5!q143je@6k1Du8rS`ZIgNgMYS zI^^VfK5JuH5w!te!dSmb$t2=BJwm4h#~%)CZHdl*;_0|gCp;cyIXMer3|^u*<@=3~ z%>WXjluwYC|7Gwq$!H``#{6+6@-#GY!Jm;A`h+JVBjZrp{1_^jD4+m{dAh1t*VP|M|3?%EX4R27$ySnbM)aRh*i5575bIj^f1S=m3Oa}PF7 zC_kx^Ad)Zp>9A_|sPfK7v@Osi!|{Fb55=or*W@j}`_zEH79X61?D<79%Zsl`@M4pc zbS^fNclC~S@rwvrz4QWai8{5;PXF z4lYnm(z;FYC##^dy|^eJ*e5QThm-s=n+8Vgw%pts#c;B>7DlxK|INx|{_7c@{k+=d zGOKzG@0&uZ*B#?yMeFr57t}@%cyF&wrnsT5J&tu23#@~(7dU)1#oV?$R}Q3?%vq9~ zMLs*aRXi!l?{#b6UUAz5B*KNNNKJpAs>z`zE@Dv*Mc0j#Ikm@~T|_L`%`ZB--|o$3 zleq^A3jbAWo6OfW;(Y6Vt7RyHQGs9*x<${V6IHlm_A{7W@XyIi*6>2i!lpESZ#@u` zrSiI-69U5lKy#(7-ER{IPd6g1e%eX(0T?f~drV3sIqj`#;X<~gFB`|Y9KV+z(w@C{ zE2*RMJ#*59PXZN{d&e-qLg!$|;H3PZS~BWy`?d+nk%ocCCG|Zhb{N4)En+ISGZr%y zfwZd)p4X*9Qtv`D=i%k_;DrWk?d)6|-|xM{JQgkVu6C_C?r+f0sj0~#(tBS57ay6h z@~*JPWWcxmX8H;L;wUpT+1!ck!=7Tj&dnS_*64nGSjta_cHi7+g*fp_we?bsAc1DT zr-~PlmJPe0x4tZ@$U7C*9`Z8#)$qyq{CdSK9uX259)Uf22)G!n9DWO*gFmXu@}FOu zAmbsH`bsIwl4P?*lVde&e?p9tU$nNhKgHv``_ZXac{hdp9za$JpRQ|%uG?OKq3G3j zr90YX#Nwn1r{X=~ufDTfG~O$Q!prAE<)i!%vli|WD&C5=kzUQ~j~W8p^VFs@{$ z*V}eAY$rACj<*!0H&N*;gyMV??Meh^jc0=m;I@9Nb)!$3|= zqm{eIzQzI~PDFfJ2X#_r?EZp&3{7Y{V1y#EdFZJzffipoLlZOY`>X=#!DU0t??$n3 zjNdFc5d=3G3hI}WiJ9d)g-76=1Q@)(Ueddz3f%m^iTy8_B)?=&yj$O0GIB(05DBB& zW82&)yQo5p%SVsqA@AxYs}ET!Hy#J2tGtUkP0M1owKw0c>tu?N^<{vnH|gErn#4xUY&s$0qJFiv zz8w#6?AjLlI(f+Jh9-WoPwrY*|d&G7%TKL4#B`fmr7jLT>D zB?*bNSz@4tc25p6K;7DopTA=m1nt#e{Ki4!hbn5}`O;;0vR?*C z|2ZvjEJaIYdUVu|dC3lHVZZJrIwCIjqVuI^K>9JA)<%OL=!WXv52CUI=mr!<=K<=f5*_0_8#T@(NOsg?W2UT+29Pi5u0)o!* zrs=(%#t+1-5WvbgiSeanxPU3s;G1GAhlRay1^3+UJrSYh-4y;@6XVgw^h^>ACwy-S z2^pkryHWU3#y1u3hgox~SE}?Pk=2$0H%5C)WWSsoB3&C|MVm}s#B8#Stjmlqo_mkH zqVH3u=~Le#?zA-e_($El`w)E%^aL;WWF29`ej7DYdpks|5mT_-Zzd(~$vb_y3But} zM=L$FtZ|)Uo5mW1F(C0@yN5>Nckiio9Nmlx>)U>sI|*@dW3}&uo?n5SOr+_4X}Y9Tk#s-C!Rq-K^xEEM1%Hyg01i5th{Z5oPB)}VnPpXlVlsPpG6)26E9buulT*QzMS9>M$;(O zDmRyKc!F?b^*aydo_)lYCMs9x#Z2~9jAQ>J-@vDIkTgbt8@EfW52(xe(6$4~tY+#z z7%goZpP7emXX*|&fjlG%S$VZzXF}tPl{I$yEuNIcNtxh-&PK~AB_pc0Ad`o}5L*$HRDa2( zP2q@5F>;0Ko~vt@|I`*LgrE71iNka{iRIo=c6=r=CQX>>405tH2Q+7%ig-YXN~1wk zG9@^ny%aIS{>T=9YdZLlpp)oV=s&|W^IxhIVS?5Sx=HRA%5uM8kaXrd-v(A^VqCNA z!ATJ2TNk*$&KImetMx03aCXDMja=>#C;Cs!(NGn+>oqz4IExwf*PVus>RVeT$uacFaHnx;RhnF!2Tn+2oN8 zPAh3bbyb%lh>yf}p5B*PRk^av&*>34)BN|D#L?K^ssX2X*av?&=)9#L)Dqj%stfGH8R7jEk&ZC z4_k7T%at()&n`){sYX5)FznT$sqd#+RN9u+_>*x$IgVlRm=G0I0vYv2_BTM9lbOHf|(D^#XZr;oDug zF8{19wrxj^!?ACJ)-Jf~klQ*yMD)7%5tbkRk#hP=bUq?&{CcZD8jbB2LxRxof~wNc zQ|D?lX*rAdDtwT#TzZMo{s)izADOZoI1SqFp18$Fo?VwO)sus^TAf_HRRRU+AFz9| zzAl6gv>+W3(t{Tse9!@2kjdWP>6J_4Yop*h5tJ{aJE>A4PzhS7zC92S}C3yUs5o4QC z-~bhI;BoX-_^UGj#^!Ud{CXN95%Fal&SNijt^N5TRA(OXjj1-1uI;@aU(MY%f%Hq` zNr!qz^zSvYBwV44ZjT8%?vDADc(hA;^gFmUf+zA*$@ZXnm5a9#zfb_BXtc-~ckgBu z#qOTnt_gqAW_Ye&zdw_V!gm7H1!=*>NvJ5E-3^uLSJVX|z#~6Uj(_YKE}t*~itxxPE~0RTSX%xO-n87NNHoOJ)1 zKnk6wN=zq3E4=N|+dnY{*%s&XW&XP+{Ts1Kwf@ko}`fZvh0t})ve^=dG(6X zkMj9VxMx-2ZJznR@)L(I?7rP2__}Sodic_}Nlt5lvIArA(zot9LoGS%1@%ATTgUpJ z`$PZR4`rw0dWk28h|?K=drSbflLi-J`&^Z!m|0|nJ?{T~;eGY=(`gsLZ9bae^=Na* zghYME3`l-5I!%HCWVD{sKkU@f67y?gz9EBZ=%Sol$9!2VKIsOynIjci7J+LwOlUCg zWA>yo!gp7{V<3hK{;s>*#98QNH`Q2EmCLaP<+681EawuODz7W|&#q&5eNVfJnUaY{ z|6;EfA0$@b#ny`ehKkwOSe&DVAFU9dI<}!a4=3cbZiG>|ncH@acjo!a!{knh3e211 zu9k5*Jwl=O(3|T1g?4Dzix+xm6=0PEEKDmAAkVyFfJk z2Znd7yask6D1%!#UGwgVjHe$8e;+nr8@n3>{=slT1U&z#wSE^vPY&O#N6@UHKYW|_ zKx0#K?a&|7x!?YclsE{o?w4d!>#+NC9@V!)e;KF&?Xhv#%rp2h=Shf0Mk9g~9D?@PVPtz?oRaT*beu;u}t@7hh&nZ(!-2)d&tYzJ0a0YF=- zF5Wz13bC3pc3`d2y!NLby+8^<8cYNC0^>S|0e`-^{7wE=3WCWQw}|6M*$5nuyJh)j z9^VF7p;XLpHzTJ<6irha(9W%h`pd=EiUql$5_F@F_`B42q&}-$?G~Twq&8O0Y%25@ zVQ@}k*2aY*LTB5|)^YTCDY7qiu79{L^bJR{gBk#hWCw53roR3e_b10tfoVZ~eAG&q z#v>wTPj4T&-QjHlWBs{{q^{?ieBVEM4UCd*h{R<&f6qXo(R65r1|B$~EU(JFbpe!~ zp}y(@6$H0fIqxE1QJsaxfZ{N~mP;e2Q~ds>GOkHvGL2b{=oB{+q)YeXmyk&ZR)OVr zJkM`2>~A4pl%)T{0zaOa&HL}%w!;hRkj&1denY)ei2A=56Ed$5uJGu|0^ zqqS4oC%H#PrH@-@8abYd)CUs@97drEyH&^{Jxeh&xgQP&V?AHZMCzZ|`x?A>=J&wu z%A6%tGI;6uv(9aemMycC-&WcR#o{Dk=#p1`X6*%DhXuW9VaU`&=&v<8rE_T($%lqo ztfQgj)w&;F;Rvg2)wx?e_Zi_@9<>=owkj)~|M(aq3ooaIFd4*NE!;;i zO9w7!(et)rTWo{l8^B3E`c(RlD$ZCgtkmrw;^l~a<-(y!nN-T4FtmrUUgxx00Waa@JT5vd7Ie|H2^%rqZUOW4_%71^=oRLEKCb;zaxE{ z_ky}onnRH^n|lYe8DW0k(X$Yhi+2ba0Hq^Ip+*$l(E|X18vyx(b6nDiAiey=g%v*Adtw zQ3qV+yK|@9*8(nd_wB-E_asQJ@ku%?B9c)guS0l zi(W(@|3Dc%wP6>7_*8$GpX)5ba@;j`#lJ;?Ba-E}CbQen9V>%}I6C-s?~v9(AbYi5 zX)tEcptIii=SXB>u3g;%ru}~?lxEBm7BigejI0d~RTdDVLe~D(cT!3&N1{`i@-?ut z7@vjqc3KrUa_RzhC!U#C#Uz;&k2%N9>5mAULd+`ePRx|QzeJAu1NzwSTZcoOe8iK* zAHS3}aM+?(GN5X$;jH=(^m=UCr83o+9+rP130>;I1q_3x7QP2p(4as5hMsMSLg|B{ z!3=G`rHx&Et|S&aQOS$SG!6UVrIZBTAjx}7>3CSH<1v6MGyVoSKo_xBQ6fGwA_4T>Px;0lR{VhwK#Y(wJOhW z7dO+ETZ?^lb*J^DBi^0xwGG;eR3cKE*Tky)ldAoBrvGz}abL8PX&y$sk*;{_nT&u? zva9V&=oM#oY|q#o&)v9j*y1dMz+p(PbNLLSA05nNGi4C48^K^=uq+rr!}nq{mFdFv zIDG?tN@C66amBvqu^H`B%{)|EWyhTVS2JW5M_EbJAa+h=yzfjXEU7+AT5|Z6aY3j4 z5I_a*lrvG#%=4vlPeFoq?k}}3mLwy9erZX%p(~Wc0?^YS$B7q_;&`~cj#P%bfX-r) z_GSCch@$*Mvv*C%>C>)|i_poAnb4nB(&7PZ=f`5l0}S13;=}>BNC;&JWxAT50plRS zjqm)Wm_OUKYI+jL$NxUvTLShU@HlI(g-GOaOc+W@vyz!698{ujYn+-2sEFGNFZM2_ zC8Thjt0}J1u-6-M<~Ns<&@cn5=V%ffxpo||2?AApID1#a5f+c$DX79aYe znfzH*>ACUD+(FDz#Qj-Rk7`rD9mgyNW`LddtBdRixyk&(APYbPhX9|T{YgYC z=jVvc`)eLQW%@p}Nmw6HJl#xtSrd#YkI#_plI)BvLqB{i*v7SUY5=ikVVTC%q;CaC z{a#6ug@Oj>YPc{{B`I75v_@SgFYh)IAVlgqE~3<_zt%FQd=30^Qyn)K;4N}vlaB1`+h zSXnP$9rX!6PL4_SUR9z+|7K%%F;Q}TI?9~KM$ISW?Tg(yx|Yy@8*xRcy}4|sJKuGd zqmo;4lgHcKSrf^V*U)h2#Fy~b;S*gHYl-1QdU}RLK`%(UlG&tiO|zdS3^d{th=cxe z@U=GNqqetrDULzRla6QknMS_Fr|e?}+AaG%y} z#q-UNO#i&x4(~TiN$1UEHbwnjK0W&D)01n2I8h46q&exo=b#m6W`s!$VeAHvA7Nos z1fEq%m#wE9j*_Uq2U`^LC!XTT!Z;rX^=1T2)xygpUH(zbdGQ=aRRhY)$6yAm?bA8^QyKmgp{9jH zo<7*>o;-MX{GKVx9?_9Y#NCLI4Ri3@%N(t`H1fTWi{3Y7?U@lghkAsGhNzDQd%d}& zNpBm*yi@NqVu_p{txNY$s5@YSeS4u_O@|Q@Pe=2A>)SkdO3)Dhf-slr!@Cx~&%0?v zaq185@!e=Qk5MY(^-?y}#=yaMDD2T@ODLcH@1e(Iw=+i?Kz+Qs3Vn?Erq$(3r zbqQrhqKl+z_Bs2iIVl}}2W}q~@3?5V_$-7brCZQBmwD zz;a}cF1rrB@tta<5)z3-%x;R*4hK2OX$hVk+22N@Mjp^#R}abKtn0Qz8WZjMZh0Qm(*e1cVAsl|U;StJS#7=dMfg!URKX9Hm zF9X7h2%OKXfkZ(Ivx@EI^t3-NLW~*&1ki!Gl`-fnYy}ugI%gBk2Yx@`&7Sxc@PK0m znl%Sc%r?-}Y!Hx4ygVFu0_C_4=dq-NZBN+T_HG^<>cbz9|39^N&kFrJII<(U(^qW- z4#NZh`Xw8HH#o5HW{X*K;Fi3NRZ|>GSNhEBYa0zc>(j|Y)Q*`rV9EXv1y6-8-J4=P z4)CW3T*~{)xW!#@G?|+LVdpHasFa6XlBfr~4y#UYZMq|lesTd^#fXd#xNB|}rE$t2 z;;Zx<%FaC>+kXk9|H0AqOW5g52MEMT9zXi}eAm>_mjznb-iE%%EyUdyjbmC~FMl&4 z2H}$=?7b*uZtyd(9iXE7(b0p^K%IW%ZBUhp{=*AwUY1ui!V*b<~4qIqiYUMC;*D4S(NV)h4tKdyOjh*gDJBqzXCc< zIH5NA;bCB$@DcJaClrZS4_MbLZY-E9MEkpG3UQ-e5i--aMAntJV*r%bYeoS5+uh#T zxL4N@u(A&u921LRim^d`ZHR^H=owj!tEVnWYJAA3tiD3jVLRZn8a#U&@?9!v_;6DO zmx*1>(X(~pSAz}(x6YMKjb5+uAvN(41WFKJPeC_?0k%%n^{B$rCTteq1PREtrl001 zU|)5n^yP1X@(>P5l|}Gm(6=xsP9(Fbe*MYU*`H*Yxuxkrx_$rB&XX_(Oh`-Gj+S?1 zM2Xd4qt3WG0&D{QqvI!g;6Cai|LG{4Lc`g=WV5~V_?GRA_Fo@v|L^BZnCon;5!p(8 z05y<~`PR5x_scSCwo8H=z!AZ;!y_oKZUG#5x9(2#Mdh)r$me*J>#9eNbH6u6+jm|& z-h!tAOg+}R>ZChd9Tzm{`d`*hvN>ZjUfi0TvrrPbyqaIr$RZ;&9xB=l^9s`Q2zwzkjmd+zqYsUHUEa6 z)>`(Wd6gbbfBWrt=F2r4dG+65Z-Tpu211_z%tF@YfC_1h$IUgj1o*(@Zl`&#Iw>sI zZ8aJ-x_Q~Cie&)Edhku3OUOe0*zg?|HIJTuK_%)f(1GHc#Wt88_am9+TE~E@qWDgI zJEJKGFQzDUD>O@l49>3^Cl+3@S^8wj6ic(Q|0z_cAL=JXc;nbHWxN)*)##*921$Zs zxl66>qnj#Wu}A1S%uV}dd8xhfSe!A{HGh?e3naKQYA4xjz1hbg?O7ak`NVeyLk2t$ z{zN8LY)OL#^&%5PK8w*S&z4(xT7Y|G)NxSIH8N~p7ZlyRcOmLgBW9<)KsfghH``g9 zJY1e6X6MaI-&q)hw2(#SGmH~;juExisN`jJ6X^3(>*x`WvCpNHY>*7W`%K+V< zEy^2pY{5?xpJZ)fmv5+Px#;N@Z0DO)li|SWkc3<$sc6(9d!lcZU=t!#0ba40Q7rN+5=HS8BGe z0&m={E`QH>df4Xp1(d3!DX`ANcYn_`{H<6n><#3IaQRkFX!d=&1*W{vzsiUT8<_js zVBt!;{~11wX;(JqKQFqBtyCdWRHpw`=yp?hrJT(*IS?mY20fd+MUgA*f=0@;XSmFB zZkjCe=LZxN8*yg=@`Vrb(R3{(>0g>7#?w%)WYC$4bjU?{9;heig23(}Z&>eM`Tel5 zvT?kryzPfED!{Kf?njbvZ0*`A8ZH|3Btqke(AqID$33W~Z+Tbr&Gbx7SJgUE=)MgG z@P-Cot2SC;DFNa$8RFGWa&;?HSIQP~mJGe4Fjzxqm|8_oSJlrj9u^iR(Rm1eFLlSR zvo`GJL@}AdnEvrNOj?nR?scZo7~FPLnnxqGoikct(noIDVI|@U%rWb__Yz?TnYD?X!Y!kFq<%q+E`!XX!iIZik zZ8FLJsIasxm$NmWlqqvW^i5P0UqgGCJf`c#nvH5*>ZgB6nif0MyrCigMAwZpb^lpD z67%ZuZ&t-kvrwgO=GtUPfYe$ON{g?a`sd>7Hp+IKxpvaI#{6ODqjCMh_nXYqKGZ^s zUxC*GRLgrGhI8t4mgrj^Hr^V+wT97Y106oEf6yNAS$Z|{)oro9ffgpgs2rmMKn1FZ z+$xED&Q|`6q_SVPO%qr#F8bqC%rAM;sO~RM{uch@;O?#~Aa*%jt2?bz+pu5N#nkhc zk57oo0cVLoNB|bRn->}sGamQlEP=*$;s&Cqg6eMXP))luraldKaHIVoB;qk+=iX%R zCa4_EBIhJNwcbwc`&5{yjr%wNgM5m5^)e^m%Zy^L-Z7HR8MLIIh~& zzCkq_h6!JW*mFGvgw1nqyVQ#x5v|%qFL{p@vaJMg|Lt3s6rpo>(=$3ib>pgVD1k{U z>CfnD_q?8EGAQL93iK47$@P;PEystSdj|_HZq7kFmqnWc{`4<{cO^QG;$EeZM6HmdivNeOzr@e7Z2)0*r7< zo}+x5M?1iMHL#B9p&dCLU=-$acRZJW*YSqFqLBVM=~XUUw~{rac1(h<0q8{a~AW2~&ggwes4eS#9+y+UDlvah3IkG$l2qUMTLDu?lvr zyv7qCPDuCYUA{25bQh*RR5Yq}B}!YSZ?wf$TuJR9titW82hwUE!fK^k)S( z(UF64oi2TWy?xCboa8G^Qk`e?g#+-s)VgjY#7Z=0y!Yzo@)6{ddw}6p*~~y?|I7T+ zrg0P&h9Tm|s0+-|4qRdO(>f}g#QSKwmJF}6+=coiBHWU%kr)qSPME z%?ouH&2;wF?zMsommYQrrPO=ov6k2b@4Bo@s=xJW^Q<~6T&T{ak!;$$V!B#8rJRbR z9CLbzF3PZQ5R!9GNjB~Wwgt9@whM@cQZt`YG{9!MWO1XVv3gKyMq>{PzowZaMy4i3 zl{|J|XW(6NwQ^M#hH@1!AY`gs_1t~V6dVEh2?uBE{K-o&X!0HS9nQD~L^}H=pfn9f z&-hW(7p^p$xpvLu!C{Mn4vRQGL)`rW(XnzU+g(-WI+aP3+FIBZS`TuUok2_S1ggjvtXtl4+g#6VNx z&hw}795DbC5X)&XQ`HHuY8jY^9M^{0z1wbbBGx1F=|gklE{^0p1XW9bC&o-8veW}HPDb5Rl9K( zvRec#qIy_Y#Qvrzm7zJ6QAEEsuAN1?D57&-AC~7-%7R(Egf(}GLBCKxJIaFKCH_&% zb`*}&@EH2T+*CQ6)RL&ft;+7}!3X=QLD+#^M;Wcz9BZwjC>8COv)Lcz`j+!HJ5w=Z z6gFr@r^WXwe#U^n^a#n@>J_C{u&M=OR27}9*q~#m$wj>+y0s|~EhW&qh|x^U6p<%i zR5n{ClS=}If>KoQ94vXM`uhz{yPb)^2ZWa#7m>4=Fx@T|nE%u{LK=?1dgVj$zrLg= zo@`X%VT<4%#SfMtOsEzjI5IL!@zCO#Y`^^^E&%%KfW5({wl8)yzg-)*xNhnQG=M^x{I=7ujfY{i zN~W6#Ncpz%)o!lv#~+@FRt%ITGIXj_zmqKzJ%AM@xH@Z-acjqyinKpes?ydDe$Bcq zW0NRV^uoQFDrV3{TN^jp0UJc;2hoor$G~J|c!SXc!|>3cyYa?2Nz?BH)-AYypQ?xH z5mrGhl1&q6$p=8vY|JC7sIk7QiRz*&SLim2+b2HZhH$cy%6o$5;%pU9Qe+!h#ZBk3 zklLw_y@e>%b4Jc2S5gHyxr5tr<%ve}OHZG3Hn!Z9p2WO9isCa$IZxGKDXa#U{ZJ_^Q`KO8%1;uW^yHza zGyMvn0>oPcg7BnE`*CMb{nk#H@(WG0zaT#uEof|Ke`}v927V*VN@jSA6wG7|#*LE) zZne{Lc5Un=5u|{gHoBmWEv%pjU|1Dq2&ykR+qizfF-4DZEyBSpm=|Ud* zMrJ-aexw(k0^lju#Wp(w_KaDCU8J4{_;5e<0@c%pm7F#W`nqbrE1(s9T$CcRZuF%* zRiAm>Zs{enwtY@q(_EMYoPmbUUozshzAfq%Om*4+>et_nZi^O2!S5H!&W2(HXlG4_ z$hf{!>D~b*XtQ?l>AL{&&kg(Zy3KSWb0w7s3#L`&bBPd+%9iSa6((!(B%;pkRtf{0f z8k41PIX=v>P9Z1y_;^5czC17Q+oKIeL;T?)KYowx8)EF*fL#Uu$*~q=6B%{!Wb;bu ziZ>SLX3d&z(}P9RmLjIbb&vDEHQuM}D-akj;(gMle|wA2d3{L_5i|hXcjIW;d2ktH8>!jx#4G(+@0yU%qrwI70Xwli+RW-TqGlc@9`QW8OSlpW~%= zZ(v0Qb*bjPHArFln*<~J8|wqR`pyBGt)e1CKlbGSBDxP8etKv}1oAX}x1eQTJ*#0M z2q-%!chj>3zTg$^p4EJK^sM-zhw&zm{=xGnzK)8H5f!p58#)hPlkyavlSD~ zN2_WkVMNN@-Cv>$f?SWgJD7<>-a^n;1{u!^ub$$Y!kLekEIG!67L1wepMBDfGkhQp z(t3{h2qLA~)sFyUo140xb>8(RGzABO_G{5)mDAyaMPSntdOgJH|TcGUVJOgBbZjwHmW@Pkjx zNrn+Lss<6_#Z12K&sE~i2@z%Vs6+u9c_ddp#q=YeEWZuss>HP?+f5oY46~wIdJ!JT zFvVTD2lST@dMIqzjM2Z!z-289`D+uv^z8zbf;c3~A7VXZdw187=U>3gXJ15?MeDTi zEK7o1z!#&tllmn?rDt6zL9c!DN*Mu=RI~W0bGjw@5(pEP2@l*^&+5_^qX@5qiGDA7 z2t0pA+5H#Z*bnAU2R*wTHp6l|YPKW#ksgYZIBwyH651?aYAoMQ+E*J6)FeP2jti5| zh9vv6Ja{ev+zsaw<{Z6TkPBP{I~?rLTJ@u{A;Cqwg3i(yC8Z4fiCk6VOqCh&XmQ4$ zHAP(I@>&KKN0yoH0h^Za%6X23J_q)ic9d+#Yrbcq#0hrp0pBZsmC34R;6D}5e|yp- z^;DFYI_iq=Oc$LS@+aPmRGajXJ7>%{wj*pnE|BpKnlKA>508pJC*wOql|Am}61e;H zXJOnwXSB!17~nC%@P7iZKv{2VZv#^7bOWMD93H$v3ja-bveW=pKy|)P%@h}~#}8M+ zD<8hB}IM35mvS{*RyY#3Sh`#6Oq&ui@SQ3KCG32VV!3G5z?z E00O#5HUIzs literal 12964 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