From 7c0b6d75494a9b70fc37102c633dc026d6400d0b Mon Sep 17 00:00:00 2001 From: panurgomatic Date: Mon, 18 Apr 2011 10:09:59 +0000 Subject: [PATCH] - Tried to optimise AI turrets code. Profiling showed a drop in used CPU, but more testing is needed. - Added scout pod. WIP. - iterator datum can be terminated even if "sleeping". git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1470 316c924e-a436-60f5-8080-3fe189b3f50e --- code/datums/helper_datums/global_iterator.dm | 37 ++- code/game/machinery/atmoalter/canister.dm | 12 + code/game/machinery/turrets.dm | 245 ++++++++----------- code/game/mecha/combat/honker.dm | 2 +- code/game/mecha/mecha.dm | 87 ++++--- code/game/mecha/mecha_wreckage.dm | 17 +- code/unused/vehicle.dm | 135 ++++++++++ tgstation.dme | 1 + 8 files changed, 339 insertions(+), 197 deletions(-) diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm index b0f0bc73eab..08546a81ed4 100644 --- a/code/datums/helper_datums/global_iterator.dm +++ b/code/datums/helper_datums/global_iterator.dm @@ -55,6 +55,7 @@ Data storage vars: var/check_for_null = 1 var/forbid_garbage = 0 var/result + var/state = 0 New(list/arguments=null,autostart=1) if(forbid_garbage) //prevents garbage collection with tag != null @@ -65,13 +66,21 @@ Data storage vars: return proc/main() + src.state = 1 while(src && control_switch) last_exec = world.timeofday if(check_for_null && has_null_args()) - return src.stop() + src.stop() + return 0 result = src.process(arglist(arg_list)) - sleep(delay) - return + if(src.delay>0) + for(var/sleep_time=src.delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace. + if(!src.control_switch) + return 0 + sleep(1) + else + sleep(src.delay) //delay can also be 0 and -1 + return 0 proc/start(list/arguments=null) if(src.active()) @@ -79,15 +88,28 @@ Data storage vars: if(arguments) if(!set_process_args(arguments)) return 0 + if(!state_check()) //the main loop is sleeping, wait for it to terminate. + return control_switch = 1 spawn() - src.main() + src.state = src.main() return 1 proc/stop() if(!src.active()) return control_switch = 0 + if(!state_check()) + return + return 1 + + proc/state_check() + var/lag = 0 + while(src.state) + sleep(1) + if(++lag>10) + log_game("The global_iterator loop \ref[src] failed to terminate in designated timeframe. The supplied arguments were {[list2params(arg_list)]}") + return 0 return 1 proc/process() @@ -97,13 +119,8 @@ Data storage vars: return control_switch proc/has_null_args() - if(null in arg_list) //Hope no "" or 0 errors here. + if(null in arg_list) return 1 -/* - for(var/V in arg_list) - if(isnull(V)) - return 1 -*/ return 0 diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 4a1be3644ed..2209e229996 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -134,6 +134,18 @@ /obj/machinery/portable_atmospherics/canister/return_air() return air_contents +/obj/machinery/portable_atmospherics/canister/proc/return_temperature() + var/datum/gas_mixture/GM = src.return_air() + if(GM && GM.volume>0) + return GM.temperature + return 0 + +/obj/machinery/portable_atmospherics/canister/proc/return_pressure() + var/datum/gas_mixture/GM = src.return_air() + if(GM && GM.volume>0) + return GM.return_pressure() + return 0 + /obj/machinery/portable_atmospherics/canister/blob_act() src.health -= 1 healthcheck() diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index e21e8ca9e74..5ce1c9d8c95 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -12,10 +12,10 @@ /area/turret_protected/Entered(O) ..() - if (istype(O, /mob)) - if (!istype(O, /mob/living/silicon)) - if (!(O in turretTargets)) - turretTargets += O +// world << "[O] entered[src.x],[src.y],[src.z]" + if (istype(O, /mob/living/carbon)) + if (!(O in turretTargets)) + turretTargets += O else if (istype(O, /obj/mecha)) var/obj/mecha/M = O if (M.occupant) @@ -24,6 +24,7 @@ return 1 /area/turret_protected/Exited(O) +// world << "[O] exited [src.x],[src.y],[src.z]" if (istype(O, /mob)) if (!istype(O, /mob/living/silicon)) if (O in turretTargets) @@ -35,16 +36,9 @@ else if (istype(O, /obj/mecha)) if (O in turretTargets) turretTargets -= O - - if (turretTargets.len == 0) - popDownTurrets() - + ..() return 1 -/area/turret_protected/proc/popDownTurrets() - for (var/obj/machinery/turret/aTurret in src) - if (!aTurret.isDown()) - aTurret.popDown() /obj/machinery/turret name = "turret" @@ -67,12 +61,19 @@ use_power = 1 idle_power_usage = 50 active_power_usage = 300 +// var/list/targets + var/atom/movable/cur_target + var/targeting_active = 0 + var/area/turret_protected/protected_area + /obj/machinery/turret/New() spark_system = new /datum/effects/system/spark_spread spark_system.set_up(5, 0, src) spark_system.attach(src) +// targets = new ..() + return /obj/machinery/turretcover name = "pop-up turret cover" @@ -108,122 +109,98 @@ src.lasers = lethal src.power_change() + +/obj/machinery/turret/proc/get_protected_area() + var/area/turret_protected/TP = get_area(src) + if(istype(TP)) + return TP + return + +/obj/machinery/turret/proc/check_target(var/atom/movable/T as mob|obj) + if(T && T in protected_area.turretTargets) + if(istype(T, /mob/living/carbon)) + var/mob/living/carbon/MC = T + if(!MC.stat) + if(!MC.lying || lasers) + return 1 + else if(istype(T, /obj/mecha)) + var/obj/mecha/ME = T + if(ME.occupant) + return 1 + return 0 + +/obj/machinery/turret/proc/get_new_target() + var/list/new_targets = new + var/new_target + for(var/mob/living/carbon/M in protected_area.turretTargets) + if(!M.stat) + if(!M.lying || lasers) + new_targets += M + for(var/obj/mecha/M in protected_area.turretTargets) + if(M.occupant) + new_targets += M + if(new_targets.len) + new_target = pick(new_targets) + return new_target + + /obj/machinery/turret/process() - listcheck() if(stat & (NOPOWER|BROKEN)) return - if(lastfired && world.time - lastfired < shot_delay) - return - lastfired = world.time - if (src.cover==null) + if(src.cover==null) src.cover = new /obj/machinery/turretcover(src.loc) - var/loc = src.loc - if (istype(loc, /turf)) - loc = loc:loc - if (!istype(loc, /area)) - world << text("Badly positioned turret - loc.loc is [].", loc) + protected_area = get_protected_area() + if(!protected_area || protected_area.turretTargets.len<=0 || !enabled) + if(!isDown() && !isPopping()) + popDown() return - var/area/area = loc - if (istype(area, /area)) - if (istype(loc, /area/turret_protected)) - src.wasvalid = 1 - var/area/turret_protected/tarea = loc + if(!check_target(cur_target)) //if current target fails target check + cur_target = get_new_target() //get new target - - if (tarea.turretTargets.len>0 && enabled) - if (!isPopping()) - if (isDown()) - popUp() - use_power = 2 - else - targetting() + if(cur_target) //if it's found, proceed +// world << "[cur_target]" + if(!isPopping()) + if(isDown()) + popUp() + use_power = 2 else - if (!isPopping()) - if (!isDown()) - popDown() - use_power = 1 - else - if (src.wasvalid) - src.die() - else - world << text("ERROR: Turret at [x], [y], [z] is NOT in a turret-protected area!") - -/obj/machinery/turret/proc/listcheck() - for (var/mob/living/carbon/guy in loc.loc) - if (guy in loc.loc:turretTargets) - continue - if (guy.lying && !lasers) - continue - if (!guy.stat) - loc.loc:turretTargets += guy + spawn() + if(!targeting_active) + targeting_active = 1 + target() + targeting_active = 0 + else if(!isPopping())//else, pop down + if(!isDown()) + popDown() + use_power = 1 + return -/obj/machinery/turret/proc/targetting() - var/mob/target - var/notarget = 0 - do +/obj/machinery/turret/proc/target() + while(src && check_target(cur_target)) + src.dir = get_dir(src, cur_target) + shootAt(cur_target) + sleep(shot_delay) + return - if (notarget >= 20) - return - if (target) - if (!istype(target.loc.loc, loc.loc)) - loc.loc:Exited(target) - target = null - if (target) - if ((target.lying && !lasers) || target.stat) - loc.loc:Exited(target) - target = null - if (!target) - listcheck() - if (!lasers) - for (var/mob/possible in loc.loc:turretTargets) - if (!istype(possible.loc.loc, loc.loc)) - loc.loc:Exited(possible) - continue - if (possible.stat) - loc.loc:Exited(possible) - notarget++ - continue - if (possible.lying) - loc.loc:Exited(possible) - notarget++ - continue - if (!target) - target = possible - notarget = 0 - break - else - for (var/mob/possible in loc.loc:turretTargets) - if (!istype(possible.loc.loc, loc.loc)) - loc.loc:Exited(possible) - continue - if (possible.stat) - loc.loc:Exited(possible) - notarget++ - continue - if (!target) - target = possible - notarget = 0 - break - if (target) - src.dir = get_dir(src, target) - if (src.enabled) - if (istype(target, /mob/living)) - if (!target.stat) - src.shootAt(target) - else - loc.loc:Exited(target) - target = null - else if (istype(target, /obj/mecha)) - var/obj/mecha/mecha = target - if(!mecha.occupant) - if (mecha in loc.loc:turretTargets) - loc.loc:turretTargets -= mecha - target = null - else - src.shootAt(target) - else sleep(1) - while(!target && loc.loc:turretTargets.len>0) +/obj/machinery/turret/proc/shootAt(var/atom/movable/target) + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + if (!istype(T) || !istype(U)) + return + var/obj/beam/a_laser/A + if (src.lasers) + A = new /obj/beam/a_laser( loc ) + use_power(500) + else + A = new /obj/bullet/electrode( loc ) + use_power(200) + A.current = T + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn( 0 ) + A.process() + return /obj/machinery/turret/proc/isDown() @@ -250,36 +227,6 @@ invisibility = 2 popping = 0 -/obj/machinery/turret/proc/shootAt(var/mob/target) - var/turf/T = loc - var/atom/U = (istype(target, /atom/movable) ? target.loc : target) - if ((!( U ) || !( T ))) - return - while(!( istype(U, /turf) )) - U = U.loc - if (!( istype(T, /turf) )) - return - - var/obj/beam/a_laser/A - if (src.lasers) - A = new /obj/beam/a_laser( loc ) - use_power(500) - else - A = new /obj/bullet/electrode( loc ) - use_power(200) - - if (!( istype(U, /turf) )) - //A = null - del(A) - return - A.current = U - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn( 0 ) - A.process() - return - return - /obj/machinery/turret/bullet_act(flag) if (flag == PROJECTILE_BULLET) src.health -= 17 @@ -613,4 +560,4 @@ A.xo = targloc.x - curloc.x A.process() sleep(2) - return \ No newline at end of file + return diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 2811cc685eb..4708d590f2e 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -38,7 +38,7 @@ IntegriHONK: [health/initial(health)*100] %)
PowerHONK charge: [isnull(cell_charge)?"Someone HONKed powerHonk!!!":"[cell.percent()]%"])
AirHONK pressure: [src.return_pressure()]HoNKs
- Internal HONKature: [src.air_contents.temperature]°honK|[src.air_contents.temperature - T0C]°honCk
+ Internal HONKature: [src.return_temperature()]°honK|[src.return_temperature() - T0C]°honCk
Lights: [lights?"on":"off"]
"} output += "HONKon systems:
" diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index c23e28ff8ed..cbf745d9c2c 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -37,11 +37,17 @@ //inner atmos machinery. Air tank mostly var/use_internal_tank = 0 + + //TODO: replace with common airtank + /* var/datum/gas_mixture/air_contents = new - var/obj/machinery/atmospherics/portables_connector/connected_port = null //filling the air tanks + var/filled = 0.5 var/gas_tank_volume = 500 - var/maximum_pressure = 30*ONE_ATMOSPHERE + */ + var/obj/machinery/atmospherics/portables_connector/connected_port = null //filling the air tanks + var/obj/machinery/portable_atmospherics/canister/internal_tank + var/max_temperature = 2500 var/internal_damage_threshold = 50 //health percentage below which internal damage is possible var/internal_damage = 0 //contains bitflags @@ -64,9 +70,12 @@ /obj/mecha/New() ..() src.icon_state += "-open" + /* src.air_contents.volume = gas_tank_volume //liters src.air_contents.temperature = T20C src.air_contents.oxygen = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + */ + internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) src.spark_system.set_up(2, 0, src) src.spark_system.attach(src) src.cell.charge = 15000 @@ -260,7 +269,7 @@ /obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) if(!src) return - if(prob(15)) + if(prob(20)) if(ignore_threshold || src.health*100/initial(src.health)Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
Air source: [use_internal_tank?"Internal Airtank":"Environment"]
Airtank pressure: [src.return_pressure()]kPa
- Internal temperature: [src.air_contents.temperature]°K|[src.air_contents.temperature - T0C]°C
+ Internal temperature: [src.return_temperature()]°K|[src.return_temperature() - T0C]°C
Lights: [lights?"on":"off"]
[src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null] "} @@ -1246,9 +1271,10 @@ delay = 20 process(var/obj/mecha/mecha) - if(mecha.air_contents && mecha.air_contents.volume > 0) - var/delta = mecha.air_contents.temperature - T20C - mecha.air_contents.temperature -= max(-10, min(10, round(delta/4,0.1))) + var/datum/gas_mixture/int_tank_air = mecha.return_air() + if(int_tank_air && int_tank_air.volume > 0) + var/delta = int_tank_air.temperature - T20C + int_tank_air.temperature -= max(-10, min(10, round(delta/4,0.1))) return /datum/global_iterator/mecha_view_stats // open and update stats window @@ -1288,24 +1314,21 @@ process(var/obj/mecha/mecha) if(!mecha.internal_damage) return src.stop() + var/datum/gas_mixture/int_tank_air = mecha.return_air() if(mecha.internal_damage & MECHA_INT_FIRE) - if(mecha.return_pressure()>mecha.maximum_pressure*1.5 && !(mecha.internal_damage&MECHA_INT_TANK_BREACH)) + if(mecha.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.internal_damage&MECHA_INT_TANK_BREACH)) mecha.internal_damage |= MECHA_INT_TANK_BREACH if(!(mecha.internal_damage & MECHA_INT_TEMP_CONTROL) && prob(5)) mecha.internal_damage &= ~MECHA_INT_FIRE mecha.occupant_message("Internal fire extinquished.") - if(mecha.air_contents && mecha.air_contents.volume > 0) //heat the air_contents - mecha.air_contents.temperature = min(6000+T0C, mecha.air_contents.temperature+rand(10,15)) - if(mecha.air_contents.temperature>mecha.max_temperature/2) + if(int_tank_air && int_tank_air.volume>0) //heat the air_contents + int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) + if(int_tank_air.temperature>mecha.max_temperature/2)//we assume that the tank contents include mecha pilot compartment. mecha.take_damage(1,"fire") if(mecha.internal_damage & MECHA_INT_TEMP_CONTROL) //stop the mecha_preserve_temp loop datum mecha.pr_int_temp_processor.stop() if(mecha.internal_damage & MECHA_INT_TANK_BREACH) //remove some air from internal tank - var/datum/gas_mixture/environment = mecha.loc.return_air() - var/env_pressure = environment.return_pressure() - var/pressure_delta = min(115 - env_pressure, (mecha.air_contents.return_pressure() - env_pressure)/2) - var/transfer_moles = 0 - if(mecha.air_contents.temperature > 0 && pressure_delta > 0) - transfer_moles = pressure_delta*environment.volume/(mecha.air_contents.temperature * R_IDEAL_GAS_EQUATION) - mecha.loc.assume_air(mecha.air_contents.remove(transfer_moles)) + if(int_tank_air) + var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.25) + mecha.loc.assume_air(leaked_gas) return diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 41e742fe923..7b947651a1c 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -15,6 +15,12 @@ var/list/crowbar_salvage = list("/obj/item/weapon/cell") var/list/equipment = new var/salvage_num = 5 + var/list/salvage + + New() + ..() + salvage = new + return /obj/decal/mecha_wreckage/ex_act(severity) if(severity < 3) @@ -51,11 +57,12 @@ user << "You failed to salvage anything valuable from [src]." salvage_num-- if(istype(W, /obj/item/weapon/crowbar)) - if(equipment.len) - var/obj/item/mecha_parts/mecha_equipment/E = pick(equipment) - if(E) - E.loc = get_turf(user) - user.visible_message("[user] pries [E] from [src].", "You pry [E] from [src].") + if(salvage.len) + var/obj/S = pick(salvage) + if(S) + S.loc = get_turf(user) + salvage -= S + user.visible_message("[user] pries [S] from [src].", "You pry [S] from [src].") return if(salvage_num<=0) user << "You can't see anything of value left on this wreck." diff --git a/code/unused/vehicle.dm b/code/unused/vehicle.dm index 594af77a7bc..1bd3d56afe0 100644 --- a/code/unused/vehicle.dm +++ b/code/unused/vehicle.dm @@ -143,3 +143,138 @@ O << text("\blue [] loads [] into []!", H, H.pulling, src) H.pulling = null + + +/obj/machinery/vehicle/space_ship + icon = 'escapepod.dmi' + icon_state = "pod" + var/datum/global_iterator/space_ship_inertial_movement/pr_inertial_movement + var/datum/global_iterator/space_ship_speed_increment/pr_speed_increment + var/last_relay = 0 + var/obj/machinery/portable_atmospherics/canister/internal_tank + + New() + ..() + internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) + pr_inertial_movement = new /datum/global_iterator/space_ship_inertial_movement(list(src),0) + pr_speed_increment = new /datum/global_iterator/space_ship_speed_increment(list(src),0) + return + + proc/inspace() + if(istype(src.loc, /turf/space)) + return 1 + return 0 + + remove_air(amount) + if(src.internal_tank) + return src.internal_tank.air_contents.remove(amount) + else + var/turf/T = get_turf(src) + return T.remove_air(amount) + + return_air() + if(src.internal_tank) + return src.internal_tank.return_air() + return + + proc/return_pressure() + if(src.internal_tank) + return src.internal_tank.return_pressure() + return 0 + + proc/return_temperature() + if(src.internal_tank) + return src.internal_tank.return_temperature() + return 0 + + Bump(var/atom/movable/A) + if(istype(A)) + step(A, src.dir) + else + pr_speed_increment.stop() + pr_inertial_movement.stop() + pr_inertial_movement.cur_delay = pr_inertial_movement.max_delay + pr_inertial_movement.desired_delay = pr_inertial_movement.max_delay + return + + process() + return + + proc/get_desired_speed() + return (pr_inertial_movement.max_delay-pr_inertial_movement.desired_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 + + proc/get_current_speed() + return (pr_inertial_movement.max_delay-pr_inertial_movement.cur_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 + +/obj/machinery/vehicle/space_ship/relaymove(mob/user as mob, direction) + spawn() + if (user.stat || world.time-last_relay<2) + return + last_relay = world.time + var/speed_change = 0 + if(direction & NORTH) + pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay-1, pr_inertial_movement.max_delay) + speed_change = 1 + else if (direction & SOUTH) + pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay+1, pr_inertial_movement.max_delay) + speed_change = 1 + else if (src.can_rotate && direction & 4) + src.dir = turn(src.dir, -90.0) + else if (src.can_rotate && direction & 8) + src.dir = turn(src.dir, 90) + if(speed_change) + //user << "Desired speed: [get_desired_speed()]%" + src.pr_speed_increment.start() + src.pr_inertial_movement.start() + return + +//should try two directional iterator datums, one for vertical, one for horizontal movement. +/datum/global_iterator/space_ship_inertial_movement + delay = 1 + var/min_delay = 0 + var/max_delay = 15 + var/desired_delay + var/cur_delay + var/last_move + + New() + ..() + desired_delay = max_delay + cur_delay = max_delay + + process(var/obj/machinery/vehicle/space_ship/SS as obj) + if(cur_delay >= max_delay) + return src.stop() + if(world.time - last_move < cur_delay) + return + last_move = world.time +/* + if(src.delay>=SS.max_delay) + return src.stop() +*/ + if(!step(SS, SS.dir) || !SS.inspace()) + src.stop() + src.cur_delay = max_delay + src.desired_delay = max_delay + if(src.delay<2) + SS.ex_act(2) + return + + proc/set_desired_delay(var/num as num) + src.desired_delay = num + return + +/datum/global_iterator/space_ship_speed_increment + delay = 4 + + process(var/obj/machinery/vehicle/space_ship/SS as obj) + if(SS.pr_inertial_movement.desired_delay!=SS.pr_inertial_movement.cur_delay) + var/delta = SS.pr_inertial_movement.desired_delay - SS.pr_inertial_movement.cur_delay + SS.pr_inertial_movement.cur_delay += delta/abs(delta) + /* + for(var/mob/M in SS) + M << "Current speed: [SS.get_current_speed()]" + */ + else + src.stop() + return diff --git a/tgstation.dme b/tgstation.dme index 21af7e5ff35..4bb88c80a4b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -760,6 +760,7 @@ #include "code\modules\power\singularity\particle_accelerator\particle_control.dm" #include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm" #include "code\modules\power\singularity\particle_accelerator\particle_power.dm" +#include "code\unused\vehicle.dm" #include "code\WorkInProgress\BrokenInhands.dm" #include "code\WorkInProgress\buildmode.dm" #include "code\WorkInProgress\Cameras.dm"