Files
CHOMPStation2/code/modules/vehicles/train.dm
CHOMPStation2StaffMirrorBot ed79946ade [MIRROR] some istype to macros (#9802)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-01-05 23:01:49 +01:00

251 lines
6.2 KiB
Plaintext

/obj/vehicle/train
name = "train"
dir = 4
move_delay = 1
health = 100
maxhealth = 100
fire_dam_coeff = 0.7
brute_dam_coeff = 0.5
var/passenger_allowed = 1
var/active_engines = 0
var/train_length = 0
var/latch_on_start = 1
var/obj/vehicle/train/lead
var/obj/vehicle/train/tow
var/open_top = TRUE
//-------------------------------------------
// Standard procs
//-------------------------------------------
/obj/vehicle/train/Initialize()
. = ..()
for(var/obj/vehicle/train/T in orange(1, src))
if(latch_on_start)
latch(T, null)
/obj/vehicle/train/Move()
var/old_loc = get_turf(src)
if((. = ..()))
if(tow)
tow.Move(old_loc)
else if(lead)
unattach()
/obj/vehicle/train/Bump(atom/Obstacle)
if(istype(Obstacle,/obj/structure/stairs)) // VOREstation edit - Stair support for towing vehicles
return ..()
if(!istype(Obstacle, /atom/movable))
return
var/atom/movable/A = Obstacle
if(!A.anchored)
var/turf/T = get_step(A, dir)
if(isturf(T))
A.Move(T) //bump things away when hit
if(emagged)
if(isliving(A))
var/mob/living/M = A
visible_message(span_red("[src] knocks over [M]!"))
M.apply_effects(5, 5) //knock people down if you hit them
M.apply_damages(22 / move_delay) // and do damage according to how fast the train is going
if(ishuman(load))
var/mob/living/D = load
to_chat(D, span_red("You hit [M]!"))
add_attack_logs(D,M,"Ran over with [src.name]")
//trains are commonly open topped, so there is a chance the projectile will hit the mob riding the train instead
/obj/vehicle/train/bullet_act(var/obj/item/projectile/Proj)
if(has_buckled_mobs() && prob(70))
var/mob/living/L = pick(buckled_mobs)
L.bullet_act(Proj)
return
..()
/obj/vehicle/train/update_icon()
if(open)
icon_state = initial(icon_state) + "_open"
else
icon_state = initial(icon_state)
//-------------------------------------------
// Vehicle procs
//-------------------------------------------
/obj/vehicle/train/explode()
if (tow)
tow.unattach()
unattach()
..()
//-------------------------------------------
// Interaction procs
//-------------------------------------------
/obj/vehicle/train/relaymove(mob/user, direction)
var/turf/T = get_step_to(src, get_step(src, direction))
if(!T)
to_chat(user, "You can't find a clear area to step onto.")
return 0
if(user != load)
if(user in src) //for handling players stuck in src - this shouldn't happen - but just in case it does
user.forceMove(T)
return 1
return 0
unload(user, direction)
to_chat(user, span_blue("You climb down from [src]."))
return 1
/obj/vehicle/train/MouseDrop_T(var/atom/movable/C, mob/user as mob)
if(user.buckled || user.stat || user.restrained() || !Adjacent(user) || !user.Adjacent(C) || !istype(C) || (user == C && !user.canmove))
return
if(istype(C,/obj/vehicle/train))
latch(C, user)
else
if(!load(C, user))
to_chat(user, span_red("You were unable to load [C] on [src]."))
/obj/vehicle/train/attack_hand(mob/user as mob)
if(user.stat || user.restrained() || !Adjacent(user))
return 0
if(user != load && (user in src))
user.forceMove(loc) //for handling players stuck in src
else if(load)
unload(user) //unload if loaded
else if(!load && !user.buckled)
load(user, user) //else try climbing on board
else
return 0
/obj/vehicle/train/verb/unlatch_v()
set name = "Unlatch"
set desc = "Unhitches this train from the one in front of it."
set category = "Object.Vehicle" //ChompEDIT - TGPanel
set src in view(1)
if(!ishuman(usr))
return
if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr))
return
unattach(usr)
//-------------------------------------------
// Latching/unlatching procs
//-------------------------------------------
//attempts to attach src as a follower of the train T
//Note: there is a modified version of this in code\modules\vehicles\cargo_train.dm specifically for cargo train engines
/obj/vehicle/train/proc/attach_to(obj/vehicle/train/T, mob/user)
if (get_dist(src, T) > 1)
if(user)
to_chat(user, span_red("[src] is too far away from [T] to hitch them together."))
return
if (lead)
if(user)
to_chat(user, span_red("[src] is already hitched to something."))
return
if (T.tow)
if(user)
to_chat(user, span_red("[T] is already towing something."))
return
//check for cycles.
var/obj/vehicle/train/next_car = T
while (next_car)
if (next_car == src)
if(user)
to_chat(user, span_red("That seems very silly."))
return
next_car = next_car.lead
//latch with src as the follower
lead = T
T.tow = src
set_dir(lead.dir)
if(user)
to_chat(user, span_blue("You hitch [src] to [T]."))
update_stats()
//detaches the train from whatever is towing it
/obj/vehicle/train/proc/unattach(mob/user)
if (!lead)
to_chat(user, span_red("[src] is not hitched to anything."))
return
lead.tow = null
lead.update_stats()
to_chat(user, span_blue("You unhitch [src] from [lead]."))
lead = null
update_stats()
/obj/vehicle/train/proc/latch(obj/vehicle/train/T, mob/user)
if(!istype(T) || !Adjacent(T))
return 0
var/T_dir = get_dir(src, T) //figure out where T is wrt src
if(dir == T_dir) //if car is ahead
src.attach_to(T, user)
else if(reverse_direction(dir) == T_dir) //else if car is behind
T.attach_to(src, user)
//returns 1 if this is the lead car of the train
/obj/vehicle/train/proc/is_train_head()
if (lead)
return 0
return 1
//-------------------------------------------------------
// Stat update procs
//
// Used for updating the stats for how long the train is.
// These are useful for calculating speed based on the
// size of the train, to limit super long trains.
//-------------------------------------------------------
/obj/vehicle/train/update_stats()
//first, seek to the end of the train
var/obj/vehicle/train/T = src
while(T.tow)
//check for cyclic train.
if (T.tow == src)
lead.tow = null
lead.update_stats()
lead = null
update_stats()
return
T = T.tow
//now walk back to the front.
var/active_engines = 0
var/train_length = 0
while(T)
train_length++
if (T.powered && T.on)
active_engines++
T.update_car(train_length, active_engines)
T = T.lead
/obj/vehicle/train/proc/update_car(var/train_length, var/active_engines)
return