Two Person Mecha for Robotics: The Only Real Solution To An Imminent Geometer Summoning 💪 (#59249) (#6177)

Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>

Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
This commit is contained in:
SkyratBot
2021-06-08 15:39:23 +12:00
committed by GitHub
co-authored by SmArtKar tralezab
parent 4bb91b318d
commit cf2c1ca19d
25 changed files with 970 additions and 56 deletions
+8
View File
@@ -953,6 +953,14 @@
///sent from mecha action buttons to the mecha they're linked to
#define COMSIG_MECHA_ACTION_TRIGGER "mecha_action_activate"
///sent from clicking while you have no equipment selected. Sent before cooldown and adjacency checks, so you can use this for infinite range things if you want.
#define COMSIG_MECHA_MELEE_CLICK "mecha_action_melee_click"
/// Prevents click from happening.
#define COMPONENT_CANCEL_MELEE_CLICK (1<<0)
///sent from clicking while you have equipment selected.
#define COMSIG_MECHA_EQUIPMENT_CLICK "mecha_action_equipment_click"
/// Prevents click from happening.
#define COMPONENT_CANCEL_EQUIPMENT_CLICK (1<<0)
// /mob/living/carbon/human signals
+2
View File
@@ -13,6 +13,8 @@
#define HAS_LIGHTS (1<<6)
#define QUIET_STEPS (1<<7)
#define QUIET_TURNS (1<<8)
///blocks using equipment and melee attacking.
#define CANNOT_INTERACT (1<<9)
#define MECHA_MELEE (1 << 0)
#define MECHA_RANGED (1 << 1)
+14 -4
View File
@@ -1,8 +1,18 @@
//Vehicle control flags
//Vehicle control flags. control flags describe access to actions in a vehicle.
#define VEHICLE_CONTROL_PERMISSION 1
#define VEHICLE_CONTROL_DRIVE 2
#define VEHICLE_CONTROL_KIDNAPPED 4 //Can't leave vehicle voluntarily, has to resist.
///controls the vehicles movement
#define VEHICLE_CONTROL_DRIVE (1<<0)
///Can't leave vehicle voluntarily, has to resist.
#define VEHICLE_CONTROL_KIDNAPPED (1<<1)
///melee attacks/shoves a vehicle may have
#define VEHICLE_CONTROL_MELEE (1<<2)
///using equipment/weapons on the vehicle
#define VEHICLE_CONTROL_EQUIPMENT (1<<3)
///changing around settings and the like.
#define VEHICLE_CONTROL_SETTINGS (1<<4)
///ez define for giving a single pilot mech all the flags it needs.
#define FULL_MECHA_CONTROL ALL
//Ridden vehicle flags
+4
View File
@@ -111,6 +111,10 @@
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE
/atom/movable/screen/fullscreen/ivanov_display
icon_state = "ivanov"
alpha = 180
/atom/movable/screen/fullscreen/impaired
icon_state = "impairedoverlay"
@@ -149,6 +149,30 @@
category = list("Exosuit Modules")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/board/savannah_ivanov_main
name = "\"Savannah-Ivanov\" Central Control module"
desc = "Allows for the construction of a \"Savannah-Ivanov\" Central Control module."
id = "savannah_ivanov_main"
build_path = /obj/item/circuitboard/mecha/savannah_ivanov/main
category = list("Exosuit Modules")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/board/savannah_ivanov_peri
name = "\"Savannah-Ivanov\" Peripherals Control module"
desc = "Allows for the construction of a \"Savannah-Ivanov\" Peripheral Control module."
id = "savannah_ivanov_peri"
build_path = /obj/item/circuitboard/mecha/savannah_ivanov/peripherals
category = list("Exosuit Modules")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/board/savannah_ivanov_targ
name = "\"Savannah-Ivanov\" Weapons & Targeting Control module"
desc = "Allows for the construction of a \"Savannah-Ivanov\" Weapons & Targeting Control module."
id = "savannah_ivanov_targ"
build_path = /obj/item/circuitboard/mecha/savannah_ivanov/targeting
category = list("Exosuit Modules")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
////////////////////////////////////////
/////////// Mecha Equpment /////////////
////////////////////////////////////////
@@ -465,6 +465,124 @@
construction_time = 300
category = list("Phazon")
//Savannah-Ivanov
/datum/design/savannah_ivanov_chassis
name = "Exosuit Chassis (\"Savannah-Ivanov\")"
id = "savannah_ivanov_chassis"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/chassis/savannah_ivanov
materials = list(/datum/material/iron=20000)
construction_time = 100
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_torso
name = "Exosuit Torso (\"Savannah-Ivanov\")"
id = "savannah_ivanov_torso"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_torso
materials = list(/datum/material/iron=20000,/datum/material/glass = 7500)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_head
name = "Exosuit Head (\"Savannah-Ivanov\")"
id = "savannah_ivanov_head"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_head
materials = list(/datum/material/iron=6000,/datum/material/glass = 10000)
construction_time = 100
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_left_arm
name = "Exosuit Left Arm (\"Savannah-Ivanov\")"
id = "savannah_ivanov_left_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_left_arm
materials = list(/datum/material/iron=15000)
construction_time = 150
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_right_arm
name = "Exosuit Right Arm (\"Savannah-Ivanov\")"
id = "savannah_ivanov_right_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_right_arm
materials = list(/datum/material/iron=15000)
construction_time = 150
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_chassis
name = "Exosuit Chassis (\"Savannah-Ivanov\")"
id = "savannah_ivanov_chassis"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/chassis/savannah_ivanov
materials = list(/datum/material/iron=25000)
construction_time = 100
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_torso
name = "Exosuit Torso (\"Savannah-Ivanov\")"
id = "savannah_ivanov_torso"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_torso
materials = list(/datum/material/iron=25000, /datum/material/glass = 10000,/datum/material/silver=10000)
construction_time = 300
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_head
name = "Exosuit Head (\"Savannah-Ivanov\")"
id = "savannah_ivanov_head"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_head
materials = list(/datum/material/iron=10000,/datum/material/glass = 15000,/datum/material/silver=2000)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_left_arm
name = "Exosuit Left Arm (\"Savannah-Ivanov\")"
id = "savannah_ivanov_left_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_left_arm
materials = list(/datum/material/iron=10000,/datum/material/silver=4000)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_right_arm
name = "Exosuit Right Arm (\"Savannah-Ivanov\")"
id = "savannah_ivanov_right_arm"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_right_arm
materials = list(/datum/material/iron=10000,/datum/material/silver=4000)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_left_leg
name = "Exosuit Left Leg (\"Savannah-Ivanov\")"
id = "savannah_ivanov_left_leg"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_left_leg
materials = list(/datum/material/iron=15000,/datum/material/silver=4000)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_right_leg
name = "Exosuit Right Leg (\"Savannah-Ivanov\")"
id = "savannah_ivanov_right_leg"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_right_leg
materials = list(/datum/material/iron=15000,/datum/material/silver=4000)
construction_time = 200
category = list("Savannah-Ivanov")
/datum/design/savannah_ivanov_armor
name = "Exosuit Armor (\"Savannah-Ivanov\")"
id = "savannah_ivanov_armor"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/part/savannah_ivanov_armor
materials = list(/datum/material/iron=30000,/datum/material/uranium=25000,/datum/material/titanium=20000)
construction_time = 600
category = list("Savannah-Ivanov")
//Clarke
/datum/design/clarke_chassis
name = "Exosuit Chassis (\"Clarke\")"
@@ -1523,6 +1523,26 @@
)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/savannah_ivanov
id = "mecha_savannah_ivanov"
display_name = "EXOSUIT: Savannah-Ivanov"
description = "Savannah-Ivanov exosuit designs"
prereq_ids = list("adv_mecha", "weaponry", "exp_tools")
design_ids = list(
"savannah_ivanov_armor",
"savannah_ivanov_chassis",
"savannah_ivanov_head",
"savannah_ivanov_left_arm",
"savannah_ivanov_left_leg",
"savannah_ivanov_main",
"savannah_ivanov_peri",
"savannah_ivanov_right_arm",
"savannah_ivanov_right_leg",
"savannah_ivanov_targ",
"savannah_ivanov_torso",
)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/adv_mecha_tools
id = "adv_mecha_tools"
display_name = "Advanced Exosuit Equipment"
+3 -2
View File
@@ -23,7 +23,7 @@
var/key_type
///The inserted key, needed on some vehicles to start the engine
var/obj/item/key/inserted_key
/// Whether the vehicle os currently able to move
/// Whether the vehicle is currently able to move
var/canmove = TRUE
var/list/autogrant_actions_passenger //plain list of typepaths
var/list/autogrant_actions_controller //assoc list "[bitflag]" = list(typepaths)
@@ -102,9 +102,10 @@
/obj/vehicle/proc/auto_assign_occupant_flags(mob/M) //override for each type that needs it. Default is assign driver if drivers is not at max.
if(driver_amount() < max_drivers)
add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
add_control_flags(M, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/proc/remove_occupant(mob/M)
SHOULD_CALL_PARENT(TRUE)
if(!istype(M))
return FALSE
remove_control_flags(M, ALL)
+1 -1
View File
@@ -40,7 +40,7 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.mind?.assigned_role == "Clown") //Ensures only clowns can drive the car. (Including more at once)
add_control_flags(H, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
add_control_flags(H, VEHICLE_CONTROL_DRIVE)
RegisterSignal(H, COMSIG_MOB_CLICKON, .proc/fire_cannon_at)
M.log_message("has entered [src] as a possible driver", LOG_ATTACK)
return
+44 -22
View File
@@ -151,8 +151,8 @@
///Cooldown between using smoke
var/smoke_cooldown = 10 SECONDS
///Bool for if the mech is currently phasing
var/phasing = FALSE
///check for phasing, if it is set to text (to describe how it is phasing: "flying", "phasing") it will let the mech walk through walls.
var/phasing = ""
///Power we use every time we phaze through something
var/phasing_energy_drain = 200
///icon_state for flick() when phazing
@@ -252,15 +252,21 @@
/obj/vehicle/sealed/mecha/update_icon_state()
if((mecha_flags & SILICON_PILOT) && silicon_icon_state)
icon_state = silicon_icon_state
return ..()
if(LAZYLEN(occupants))
icon_state = base_icon_state
return ..()
icon_state = "[base_icon_state]-open"
icon_state = get_mecha_occupancy_state()
return ..()
//override this proc if you need to split up mecha control between multiple people (see savannah_ivanov.dm)
/obj/vehicle/sealed/mecha/auto_assign_occupant_flags(mob/M)
if(driver_amount() < max_drivers)
add_control_flags(M, FULL_MECHA_CONTROL)
/obj/vehicle/sealed/mecha/proc/get_mecha_occupancy_state()
if((mecha_flags & SILICON_PILOT) && silicon_icon_state)
return silicon_icon_state
if(LAZYLEN(occupants))
return base_icon_state
return "[base_icon_state]-open"
/obj/vehicle/sealed/mecha/CanPassThrough(atom/blocker, turf/target, blocker_opinion)
if(!phasing || get_charge() <= phasing_energy_drain || throwing)
return ..()
@@ -515,18 +521,18 @@
SIGNAL_HANDLER
if(!isturf(target) && !isturf(target.loc)) // Prevents inventory from being drilled
return
if(completely_disabled || is_currently_ejecting)
if(completely_disabled || is_currently_ejecting || (mecha_flags & CANNOT_INTERACT))
return
var/list/modifiers = params2list(params)
if(isAI(user) == !LAZYACCESS(modifiers, MIDDLE_CLICK))//BASICALLY if a human uses MMB, or an AI doesn't, then do nothing.
return
if(phasing)
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Unable to interact with objects while phasing.</span>")
balloon_alert(user, "not while [phasing]!")
return
if(user.incapacitated())
return
if(construction_state)
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Maintenance protocols in effect.</span>")
balloon_alert(user, "end maintenance first!")
return
if(!get_charge())
return
@@ -539,22 +545,37 @@
target = pick(view(3,target))
var/mob/living/livinguser = user
if(selected)
if(!(livinguser in return_controllers_with_flag(VEHICLE_CONTROL_EQUIPMENT)))
balloon_alert(user, "wrong seat for equipment!")
return
if(!Adjacent(target) && (selected.range & MECHA_RANGED))
if(HAS_TRAIT(livinguser, TRAIT_PACIFISM) && selected.harmful)
to_chat(livinguser, "<span class='warning'>You don't want to harm other living beings!</span>")
return
if(SEND_SIGNAL(src, COMSIG_MECHA_EQUIPMENT_CLICK, livinguser, target) & COMPONENT_CANCEL_EQUIPMENT_CLICK)
return
INVOKE_ASYNC(selected, /obj/item/mecha_parts/mecha_equipment.proc/action, user, target, params)
return
if((selected.range & MECHA_MELEE) && Adjacent(target))
if(isliving(target) && selected.harmful && HAS_TRAIT(livinguser, TRAIT_PACIFISM))
to_chat(livinguser, "<span class='warning'>You don't want to harm other living beings!</span>")
return
if(SEND_SIGNAL(src, COMSIG_MECHA_EQUIPMENT_CLICK, livinguser, target) & COMPONENT_CANCEL_EQUIPMENT_CLICK)
return
INVOKE_ASYNC(selected, /obj/item/mecha_parts/mecha_equipment.proc/action, user, target, params)
return
if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MELEE_ATTACK) || !Adjacent(target))
if(!(livinguser in return_controllers_with_flag(VEHICLE_CONTROL_MELEE)))
to_chat(livinguser, "<span class='warning'>You're in the wrong seat to interact with your hands.</span>")
return
var/on_cooldown = TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MELEE_ATTACK)
var/adjacent = Adjacent(target)
if(SEND_SIGNAL(src, COMSIG_MECHA_MELEE_CLICK, livinguser, target, on_cooldown, adjacent) & COMPONENT_CANCEL_MELEE_CLICK)
return
if(on_cooldown || !adjacent)
return
if(internal_damage & MECHA_INT_CONTROL_LOST)
target = pick(oview(1,src))
target.mech_melee_attack(src, user)
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown)
@@ -604,9 +625,10 @@
return FALSE
/obj/vehicle/sealed/mecha/relaymove(mob/living/user, direction)
if(canmove)
vehicle_move(direction)
return TRUE
. = TRUE
if(!canmove || !(user in return_drivers()))
return
vehicle_move(direction)
/obj/vehicle/sealed/mecha/vehicle_move(direction, forcerotate = FALSE)
if(!COOLDOWN_FINISHED(src, cooldown_vehicle_move))
@@ -691,7 +713,7 @@
. = ..()
if(phasing) //Theres only one cause for phasing canpass fails
addtimer(VARSET_CALLBACK(src, movedelay, TRUE), movedelay*3)
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>A dull, universal force is preventing you from phasing here!</span>")
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>A dull, universal force is preventing you from [phasing] here!</span>")
spark_system.start()
return
if(.) //mech was thrown/door/whatever
@@ -934,11 +956,11 @@
/obj/vehicle/sealed/mecha/generate_actions()
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_eject)
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_internals)
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_cycle_equip)
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_lights)
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_view_stats)
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/strafe)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_internals, VEHICLE_CONTROL_SETTINGS)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/mech_cycle_equip, VEHICLE_CONTROL_EQUIPMENT)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_lights, VEHICLE_CONTROL_SETTINGS)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/mech_view_stats, VEHICLE_CONTROL_SETTINGS)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/strafe, VEHICLE_CONTROL_DRIVE)
/obj/vehicle/sealed/mecha/proc/moved_inside(mob/living/newoccupant)
if(!(newoccupant?.client))
@@ -0,0 +1,393 @@
///how much time between charge_level going up by 1
#define SKYFALL_SINGLE_CHARGE_TIME 2 SECONDS
///enough charge level to take off, basically done charging
#define SKYFALL_CHARGELEVEL_LAUNCH 5
///the first half of the leap, where the mech is flying upwards.
#define SKYFALL_LEAP_ARCING_UP 1
///the second half of the leap, where the mech is flying downwards.
#define SKYFALL_LEAP_ARCING_DOWN 1
///how much time you're in the air
#define TOTAL_SKYFALL_LEAP_TIME 3 SECONDS
/**
* ## Savannah-Ivanov!
*
* A two person mecha that delegates moving to the driver and shooting to the pilot.
* ...Hilarious, right?
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov
name = "\improper Savannah-Ivanov"
desc = "An insanely overbulked mecha that handily crushes single-pilot opponents. The price is that you need two pilots to use it."
icon = 'icons/mecha/coop_mech.dmi'
base_icon_state = "savannah_ivanov"
icon_state = "savannah_ivanov_0_0"
movedelay = 3
dir_in = 2 //Facing South.
max_integrity = 450 //really tanky, like damn
deflect_chance = 25
armor = list(MELEE = 45, BULLET = 40, LASER = 30, ENERGY = 30, BOMB = 40, BIO = 0, RAD = 80, FIRE = 100, ACID = 100)
max_temperature = 30000
infra_luminosity = 3
wreckage = /obj/structure/mecha_wreckage/savannah_ivanov
internal_damage_threshold = 25
max_occupants = 2
//no tax on flying, since the power cost is in the leap itself.
phasing_energy_drain = 0
///skyfall ability cooldown
COOLDOWN_DECLARE(skyfall_cooldown)
///cooldown time between skyfall uses
var/skyfall_cooldown_time = 1 MINUTES
///skyfall builds up in charges every 2 seconds, when it reaches 5 charges the ability actually starts
var/skyfall_charge_level = 0
///ivanov strike ability cooldown
COOLDOWN_DECLARE(strike_cooldown)
///cooldown time between strike uses
var/strike_cooldown_time = 40 SECONDS
///toggled by ivanov strike, TRUE when signals are hooked to intercept clicks.
var/aiming_ivanov = FALSE
///how many rockets can we send with ivanov strike
var/rockets_left = 0
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/get_mecha_occupancy_state()
var/driver_present = driver_amount() != 0
var/gunner_present = return_amount_of_controllers_with_flag(VEHICLE_CONTROL_EQUIPMENT) > 0
var/leap_state = skyfall_charge_level > 2 ? "leap_" : ""
return "[base_icon_state]_[leap_state][gunner_present]_[driver_present]"
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/auto_assign_occupant_flags(mob/new_occupant)
if(driver_amount() < max_drivers) //movement
add_control_flags(new_occupant, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
else //weapons
add_control_flags(new_occupant, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/generate_actions()
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/swap_seat)
. = ..()
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/skyfall, VEHICLE_CONTROL_DRIVE)
initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/ivanov_strike, VEHICLE_CONTROL_EQUIPMENT)
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/remove_occupant(mob/getting_out)
//gunner getting out ends any ivanov aiming
if(aiming_ivanov && (getting_out in return_controllers_with_flag(VEHICLE_CONTROL_EQUIPMENT)))
end_missile_targeting(getting_out)
. = ..()
/**
* ## begin_skyfall_charge
*
* Proc called by the mecha's ability that starts the skyfall loop
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/begin_skyfall_charge(mob/pilot)
balloon_alert(pilot, "charging skyfall...")
INVOKE_ASYNC(src, .proc/skyfall_charge_loop, pilot)
/**
* ## skyfall_charge_loop
*
* The actual skyfall loop itself. Repeatedly calls itself after a do_after, so any interruptions will call abort_skyfall and end the loop
* the other way the loop ends is if charge level (var it's ticking up) gets to SKYFALL_CHARGELEVEL_LAUNCH, in which case it ends the loop and does the ability.
* arguments:
* * pilot: mob that activated the skyfall ability
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/skyfall_charge_loop(mob/living/pilot)
if(!pilot || !(pilot in return_drivers()) || !do_after(pilot, SKYFALL_SINGLE_CHARGE_TIME, target = src))
abort_skyfall(pilot)
return
skyfall_charge_level++
switch(skyfall_charge_level)
if(1)
visible_message("<span class='warning'>[src] clicks and whirrs for a moment, with a low hum emerging from the legs.</span>")
playsound(src, 'sound/items/rped.ogg', 50, TRUE)
if(2)
visible_message("<span class='warning'>[src] begins to shake, the sounds of electricity growing louder.</span>")
Shake(5, 5, SKYFALL_SINGLE_CHARGE_TIME-1) // -1 gives space between the animates, so they don't interrupt eachother
if(3)
visible_message("<span class='warning'>[src] assumes a pose as it rattles violently.</span>")
Shake(7, 7, SKYFALL_SINGLE_CHARGE_TIME-1) // -1 gives space between the animates, so they don't interrupt eachother
spark_system.start()
update_icon_state()
if(4)
visible_message("<span class='warning'>[src] sparks and shutters as it finalizes preparation.</span>")
playsound(src, 'sound/mecha/skyfall_power_up.ogg', 50, TRUE)
Shake(10, 10, SKYFALL_SINGLE_CHARGE_TIME-1) // -1 gives space between the animates, so they don't interrupt eachother
spark_system.start()
if(SKYFALL_CHARGELEVEL_LAUNCH)
visible_message("<span class='danger'>[src] leaps into the air!</span>")
playsound(src, 'sound/weapons/gun/general/rocket_launch.ogg', 50, TRUE)
if(skyfall_charge_level != SKYFALL_CHARGELEVEL_LAUNCH)
INVOKE_ASYNC(src, .proc/skyfall_charge_loop, pilot)
return
COOLDOWN_START(src, skyfall_cooldown, skyfall_cooldown_time)
var/datum/action/vehicle/sealed/mecha/savannah_action = occupant_actions[pilot][/datum/action/vehicle/sealed/mecha/skyfall]
savannah_action.button_icon_state = "mech_savannah_cooldown"
savannah_action.UpdateButtonIcon()
addtimer(CALLBACK(savannah_action, /datum/action/vehicle/sealed/mecha/skyfall.proc/reset_button_icon), skyfall_cooldown_time)
for(var/mob/living/shaken in range(7, src))
shake_camera(shaken, 3, 3)
var/turf/launch_turf = get_turf(src)
new /obj/effect/hotspot(launch_turf)
launch_turf.hotspot_expose(700, 50, 1)
new /obj/effect/skyfall_landingzone(launch_turf, src)
resistance_flags |= INDESTRUCTIBLE //not while jumping at least
mecha_flags |= QUIET_STEPS|QUIET_TURNS|CANNOT_INTERACT
phasing = "flying"
movedelay = 1
density = FALSE
layer = FLY_LAYER
animate(src, alpha = 0, time = 8, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
animate(src, pixel_z = 400, time = 10, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) //Animate our rising mech (just like pods hehe)
addtimer(CALLBACK(src, .proc/begin_landing, pilot), 2 SECONDS)
/**
* ## begin_landing
*
* Called by skyfall_charge_loop after some time if it reaches full charge level.
* it's just the animations of the mecha coming down + another timer for the final landing effect
* arguments:
* * pilot: mob that activated the skyfall ability
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/begin_landing(mob/living/pilot)
animate(src, pixel_z = 0, time = 10, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
animate(src, alpha = 255, time = 8, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, .proc/land, pilot), 10)
/**
* ## begin_landing
*
* Called by skyfall_charge_loop after some time if it reaches full charge level.
* it's just the animations of the mecha coming down + another timer for the final landing effect
* arguments:
* * pilot: mob that activated the skyfall ability
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/land(mob/living/pilot)
visible_message("<span class='danger'>[src] lands from above!</span>")
playsound(src, 'sound/effects/explosion1.ogg', 50, 1)
resistance_flags &= ~INDESTRUCTIBLE
mecha_flags &= ~(QUIET_STEPS|QUIET_TURNS|CANNOT_INTERACT)
phasing = initial(phasing)
movedelay = initial(movedelay)
density = TRUE
layer = initial(layer)
skyfall_charge_level = 0
update_icon_state()
for(var/mob/living/shaken in range(7, src))
shake_camera(shaken, 5, 5)
var/turf/landed_on = get_turf(src)
for(var/thing in range(1, src))
if(isopenturf(thing))
var/turf/open/floor/crushed_tile = thing
crushed_tile.break_tile()
if(isclosedturf(thing) && thing == landed_on)
var/turf/closed/crushed_wall = thing
crushed_wall.ScrapeAway()
if(isobj(thing))
var/obj/crushed_object = thing
if(crushed_object == src)
continue
crushed_object.take_damage(150) //same as a hulk punch, makes sense to me
if(isliving(thing))
var/mob/living/crushed_victim = thing
if(crushed_victim in occupants)
continue
if(crushed_victim in landed_on)
to_chat(crushed_victim, "<span class='userdanger'>[src] crashes down on you from above!</span>")
if(crushed_victim.stat != CONSCIOUS)
crushed_victim.gib(FALSE, FALSE, FALSE)
else
crushed_victim.adjustBruteLoss(80)
else
to_chat(crushed_victim, "<span class='userdanger'>The tremors from [src] landing sends you flying!</span>")
var/fly_away_direction = get_dir(src, crushed_victim)
crushed_victim.throw_at(get_edge_target_turf(crushed_victim, fly_away_direction), 4, 3)
crushed_victim.adjustBruteLoss(15)
/**
* ## abort_skyfall
*
* Called by skyfall_charge_loop if the charging is interrupted.
* Applies cooldown and resets charge level
* arguments:
* * pilot: mob that failed the skyfall ability
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/abort_skyfall(mob/pilot)
if(pilot)
balloon_alert(pilot, "skyfall aborted")
COOLDOWN_START(src, skyfall_cooldown, skyfall_charge_level * 10 SECONDS) //so aborting skyfall later in the process imposes a longer cooldown
skyfall_charge_level = 0
update_icon_state()
/**
* ## start_missile_targeting
*
* Called by the ivanov strike datum action, hooks signals into clicking to call drop_missile
* Plus other flavor like the overlay
* arguments:
* * gunner: mob that activated the ivanov strike
* * silent: whether to send feedback messages.
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/start_missile_targeting(mob/gunner)
balloon_alert(gunner, "missile mode on (click to target)")
aiming_ivanov = TRUE
rockets_left = 3
RegisterSignal(src, COMSIG_MECHA_MELEE_CLICK, .proc/on_melee_click)
RegisterSignal(src, COMSIG_MECHA_EQUIPMENT_CLICK, .proc/on_equipment_click)
gunner.client.mouse_override_icon = 'icons/effects/mouse_pointers/supplypod_down_target.dmi'
gunner.update_mouse_pointer()
gunner.overlay_fullscreen("ivanov", /atom/movable/screen/fullscreen/ivanov_display, 1)
SEND_SOUND(gunner, 'sound/machines/terminal_on.ogg') //spammable so I don't want to make it audible to anyone else
/**
* ## end_missile_targeting
*
* Called by the ivanov strike datum action or other actions that would end targetting
* Unhooks signals into clicking to call drop_missile plus other flavor like the overlay
* arguments:
* * gunner: mob that activated the ivanov strike
* * silent: whether to send feedback messages.
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/end_missile_targeting(mob/gunner)
aiming_ivanov = FALSE
rockets_left = 0
UnregisterSignal(src, list(COMSIG_MECHA_MELEE_CLICK, COMSIG_MECHA_EQUIPMENT_CLICK))
gunner.client.mouse_override_icon = null
gunner.update_mouse_pointer()
gunner.clear_fullscreen("ivanov")
///signal called from clicking with no equipment
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/on_melee_click(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent)
SIGNAL_HANDLER
if(!target)
return
drop_missile(pilot, get_turf(target))
///signal called from clicking with equipment
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/on_equipment_click(datum/source, mob/living/pilot, atom/target)
SIGNAL_HANDLER
if(!target)
return
drop_missile(pilot, get_turf(target))
/**
* ## drop_missile
*
* Called via intercepted clicks when the missile ability is active
* Spawns a droppod and starts the cooldown of the missile strike ability
* arguments:
* * gunner: mob that activated the ivanov strike
* * target_turf: turf of the atom that was clicked on
*/
/obj/vehicle/sealed/mecha/combat/savannah_ivanov/proc/drop_missile(mob/gunner, turf/target_turf)
rockets_left -= 1
if(rockets_left <= 0)
end_missile_targeting(gunner)
SEND_SOUND(gunner, 'sound/machines/triple_beep.ogg')
COOLDOWN_START(src, strike_cooldown, strike_cooldown_time)
podspawn(list(
"target" = target_turf,
"style" = STYLE_MISSILE,
"effectMissile" = TRUE,
"explosionSize" = list(0,0,1,2)
))
var/datum/action/vehicle/sealed/mecha/strike_action = occupant_actions[gunner][/datum/action/vehicle/sealed/mecha/ivanov_strike]
strike_action.button_icon_state = "mech_ivanov_cooldown"
strike_action.UpdateButtonIcon()
addtimer(CALLBACK(strike_action, /datum/action/vehicle/sealed/mecha/ivanov_strike.proc/reset_button_icon), strike_cooldown_time)
///Savannah Skyfall
/datum/action/vehicle/sealed/mecha/skyfall
name = "Savannah Skyfall"
button_icon_state = "mech_savannah"
/datum/action/vehicle/sealed/mecha/skyfall/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
var/obj/vehicle/sealed/mecha/combat/savannah_ivanov/savannah_mecha = chassis
if(savannah_mecha.phasing)
to_chat(owner, "<span class='warning'>You're already airborne!</span>")
return
if(!COOLDOWN_FINISHED(savannah_mecha, skyfall_cooldown))
var/timeleft = COOLDOWN_TIMELEFT(savannah_mecha, skyfall_cooldown)
to_chat(owner, "<span class='warning'>You need to wait [DisplayTimeText(timeleft, 1)] before attempting to Skyfall.</span>")
return
if(savannah_mecha.skyfall_charge_level)
savannah_mecha.abort_skyfall(owner)
return
savannah_mecha.begin_skyfall_charge(owner)
/**
* ## reset_button_icon
*
* called after an addtimer when the cooldown is finished with the skyfall, resets the icon
*/
/datum/action/vehicle/sealed/mecha/skyfall/proc/reset_button_icon()
button_icon_state = "mech_savannah"
UpdateButtonIcon()
/datum/action/vehicle/sealed/mecha/ivanov_strike
name = "Ivanov Strike"
button_icon_state = "mech_ivanov"
/datum/action/vehicle/sealed/mecha/ivanov_strike/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
var/obj/vehicle/sealed/mecha/combat/savannah_ivanov/ivanov_mecha = chassis
if(!COOLDOWN_FINISHED(ivanov_mecha, strike_cooldown))
var/timeleft = COOLDOWN_TIMELEFT(ivanov_mecha, strike_cooldown)
to_chat(owner, "<span class='warning'>You need to wait [DisplayTimeText(timeleft, 1)] before firing another Ivanov Strike.</span>")
return
if(ivanov_mecha.aiming_ivanov)
ivanov_mecha.end_missile_targeting(owner)
else
ivanov_mecha.start_missile_targeting(owner)
/**
* ## reset_button_icon
*
* called after an addtimer when the cooldown is finished with the ivanov strike, resets the icon
*/
/datum/action/vehicle/sealed/mecha/ivanov_strike/proc/reset_button_icon()
button_icon_state = "mech_ivanov"
UpdateButtonIcon()
//misc effects
///a simple indicator of where the skyfall is going to land.
/obj/effect/skyfall_landingzone
name = "Landing Zone Indicator"
desc = "A holographic projection designating the landing zone of something. It's probably best to stand back."
icon = 'icons/mob/telegraphing/telegraph_96x96.dmi'
icon_state = "target_largebox"
layer = BELOW_MOB_LAYER
pixel_x = -32
pixel_y = -32
alpha = 0
///reference to mecha following
var/obj/vehicle/sealed/mecha/combat/mecha
/obj/effect/skyfall_landingzone/Initialize(mapload, obj/vehicle/sealed/mecha/combat/mecha)
. = ..()
src.mecha = mecha
animate(src, alpha = 255, TOTAL_SKYFALL_LEAP_TIME/2, easing = CIRCULAR_EASING|EASE_OUT)
RegisterSignal(mecha, COMSIG_MOVABLE_MOVED, .proc/follow)
QDEL_IN(src, TOTAL_SKYFALL_LEAP_TIME) //when the animations land
/obj/effect/skyfall_landingzone/Destroy(force)
. = ..()
UnregisterSignal(mecha, COMSIG_MOVABLE_MOVED)
mecha = null
///called when the mecha moves
/obj/effect/skyfall_landingzone/proc/follow(datum/source_mecha)
SIGNAL_HANDLER
forceMove(get_turf(source_mecha))
#undef SKYFALL_SINGLE_CHARGE_TIME
#undef SKYFALL_CHARGELEVEL_LAUNCH
#undef SKYFALL_LEAP_ARCING_UP
#undef SKYFALL_LEAP_ARCING_DOWN
#undef TOTAL_SKYFALL_LEAP_TIME
@@ -53,6 +53,7 @@
"Durand",
"H.O.N.K",
"Phazon",
"Savannah-Ivanov",
"Exosuit Equipment",
"Exosuit Ammunition",
"Cyborg Upgrade Modules",
+47 -9
View File
@@ -33,6 +33,7 @@
/datum/action/vehicle/sealed/mecha/mech_toggle_internals/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
chassis.use_internal_tank = !chassis.use_internal_tank
button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
chassis.balloon_alert(owner, "taking air from [chassis.use_internal_tank ? "internal airtank" : "environment"]")
@@ -88,6 +89,7 @@
/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
if(!(chassis.mecha_flags & HAS_LIGHTS))
chassis.balloon_alert(owner, "the mech lights are broken!")
return
@@ -108,6 +110,7 @@
/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
var/datum/browser/popup = new(owner , "exosuit")
popup.set_content(chassis.get_stats_html(owner))
popup.open()
@@ -124,8 +127,13 @@
chassis.toggle_strafe()
/obj/vehicle/sealed/mecha/AltClick(mob/living/user)
if((user in occupants) && user.canUseTopic(src))
toggle_strafe()
if(!(user in occupants) || !user.canUseTopic(src))
return
if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE)))
to_chat(user, "<span class='warning'>You're in the wrong seat to control movement.</span>")
return
toggle_strafe()
/obj/vehicle/sealed/mecha/proc/toggle_strafe()
if(!(mecha_flags & CANSTRAFE))
@@ -215,14 +223,14 @@
return
var/new_damtype
switch(chassis.damtype)
if("tox")
new_damtype = "brute"
if(TOX)
new_damtype = BRUTE
chassis.balloon_alert(owner, "your punches will now deal brute damage")
if("brute")
new_damtype = "fire"
if(BRUTE)
new_damtype = BURN
chassis.balloon_alert(owner, "your punches will now deal burn damage")
if("fire")
new_damtype = "tox"
if(BURN)
new_damtype = TOX
chassis.balloon_alert(owner,"your punches will now deal toxin damage")
chassis.damtype = new_damtype
button_icon_state = "mech_damtype_[new_damtype]"
@@ -236,7 +244,37 @@
/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
chassis.phasing = !chassis.phasing
chassis.phasing = chassis.phasing ? "" : "phasing"
button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]"
chassis.balloon_alert(owner, "[chassis.phasing ? "enabled" : "disabled"] phasing")
UpdateButtonIcon()
///swap seats, for two person mecha
/datum/action/vehicle/sealed/mecha/swap_seat
name = "Switch Seats"
button_icon_state = "mech_seat_swap"
/datum/action/vehicle/sealed/mecha/swap_seat/Trigger()
if(!owner || !chassis || !(owner in chassis.occupants))
return
if(chassis.occupants.len == chassis.max_occupants)
chassis.balloon_alert(owner, "other seat occupied!")
return
var/list/drivers = chassis.return_drivers()
chassis.balloon_alert(owner, "moving to other seat...")
chassis.is_currently_ejecting = TRUE
if(!do_after(owner, chassis.has_gravity() ? chassis.exit_delay : 0 , target = chassis))
chassis.balloon_alert(owner, "interrupted!")
chassis.is_currently_ejecting = FALSE
return
chassis.is_currently_ejecting = FALSE
if(owner in drivers)
chassis.balloon_alert(owner, "controlling gunner seat")
chassis.remove_control_flags(owner, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
chassis.add_control_flags(owner, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
else
chassis.balloon_alert(owner, "controlling pilot seat")
chassis.remove_control_flags(owner, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
chassis.add_control_flags(owner, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS)
chassis.update_icon_state()
@@ -1202,6 +1202,148 @@
"<span class='notice'>You slowly place the bluespace anomaly core into its socket and close its chamber.</span>")
return TRUE
//savannah_ivanov
/datum/component/construction/unordered/mecha_chassis/savannah_ivanov
result = /datum/component/construction/mecha/savannah_ivanov
steps = list(
/obj/item/mecha_parts/part/savannah_ivanov_torso,
/obj/item/mecha_parts/part/savannah_ivanov_head,
/obj/item/mecha_parts/part/savannah_ivanov_left_arm,
/obj/item/mecha_parts/part/savannah_ivanov_right_arm,
/obj/item/mecha_parts/part/savannah_ivanov_left_leg,
/obj/item/mecha_parts/part/savannah_ivanov_right_leg
)
/datum/component/construction/mecha/savannah_ivanov
result = /obj/vehicle/sealed/mecha/combat/savannah_ivanov
base_icon = "savannah_ivanov"
circuit_control = /obj/item/circuitboard/mecha/savannah_ivanov/main
circuit_periph = /obj/item/circuitboard/mecha/savannah_ivanov/peripherals
circuit_weapon = /obj/item/circuitboard/mecha/savannah_ivanov/targeting
inner_plating = /obj/item/stack/sheet/plasteel
inner_plating_amount = 10
outer_plating = /obj/item/mecha_parts/part/savannah_ivanov_armor
outer_plating_amount = 1
/datum/component/construction/mecha/savannah_ivanov/custom_action(obj/item/I, mob/living/user, diff)
. = ..()
if(!.)
return FALSE
switch(index)
if(1)
user.visible_message("<span class='notice'>[user] connects [parent] hydraulic systems.</span>", "<span class='notice'>You connect [parent] hydraulic systems.</span>")
if(2)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] activates [parent] hydraulic systems.</span>", "<span class='notice'>You activate [parent] hydraulic systems.</span>")
else
user.visible_message("<span class='notice'>[user] disconnects [parent] hydraulic systems.</span>", "<span class='notice'>You disconnect [parent] hydraulic systems.</span>")
if(3)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] adds the wiring to [parent].</span>", "<span class='notice'>You add the wiring to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] deactivates [parent] hydraulic systems.</span>", "<span class='notice'>You deactivate [parent] hydraulic systems.</span>")
if(4)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] adjusts the wiring of [parent].</span>", "<span class='notice'>You adjust the wiring of [parent].</span>")
else
user.visible_message("<span class='notice'>[user] removes the wiring from [parent].</span>", "<span class='notice'>You remove the wiring from [parent].</span>")
if(5)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] into [parent].</span>", "<span class='notice'>You install [I] into [parent].</span>")
else
user.visible_message("<span class='notice'>[user] disconnects the wiring of [parent].</span>", "<span class='notice'>You disconnect the wiring of [parent].</span>")
if(6)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the mainboard.</span>", "<span class='notice'>You secure the mainboard.</span>")
else
user.visible_message("<span class='notice'>[user] removes the central control module from [parent].</span>", "<span class='notice'>You remove the central computer mainboard from [parent].</span>")
if(7)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] into [parent].</span>", "<span class='notice'>You install [I] into [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the mainboard.</span>", "<span class='notice'>You unfasten the mainboard.</span>")
if(8)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the ivanov peripherals control module.</span>", "<span class='notice'>You secure the ivanov peripherals control module.</span>")
else
user.visible_message("<span class='notice'>[user] removes the ivanov peripherals control module from [parent].</span>", "<span class='notice'>You remove the ivanov peripherals control module from [parent].</span>")
if(9)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] into [parent].</span>", "<span class='notice'>You install [I] into [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the ivanov peripherals control module.</span>", "<span class='notice'>You unfasten the ivanov peripherals control module.</span>")
if(10)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the ivanov weapon control module.</span>", "<span class='notice'>You secure the ivanov weapon control module.</span>")
else
user.visible_message("<span class='notice'>[user] removes the ivanov weapon control module from [parent].</span>", "<span class='notice'>You remove the ivanov weapon control module from [parent].</span>")
if(11)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] to [parent].</span>", "<span class='notice'>You install [I] to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the ivanov weapon control module.</span>", "<span class='notice'>You unfasten the ivanov weapon control module.</span>")
if(12)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the scanner module.</span>", "<span class='notice'>You secure the scanner module.</span>")
else
user.visible_message("<span class='notice'>[user] removes the scanner module from [parent].</span>", "<span class='notice'>You remove the scanner module from [parent].</span>")
if(13)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] to [parent].</span>", "<span class='notice'>You install [I] to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the scanner module.</span>", "<span class='notice'>You unfasten the scanner module.</span>")
if(14)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the capacitor.</span>", "<span class='notice'>You secure the capacitor.</span>")
else
user.visible_message("<span class='notice'>[user] removes the capacitor from [parent].</span>", "<span class='notice'>You remove the capacitor from [parent].</span>")
if(15)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] into [parent].</span>", "<span class='notice'>You install [I] into [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the capacitor.</span>", "<span class='notice'>You unfasten the capacitor.</span>")
if(16)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the power cell.</span>", "<span class='notice'>You secure the power cell.</span>")
else
user.visible_message("<span class='notice'>[user] pries the power cell from [parent].</span>", "<span class='notice'>You pry the power cell from [parent].</span>")
if(17)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs the internal armor layer to [parent].</span>", "<span class='notice'>You install the internal armor layer to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the power cell.</span>", "<span class='notice'>You unfasten the power cell.</span>")
if(18)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures the internal armor layer.</span>", "<span class='notice'>You secure the internal armor layer.</span>")
else
user.visible_message("<span class='notice'>[user] pries internal armor layer from [parent].</span>", "<span class='notice'>You pry internal armor layer from [parent].</span>")
if(19)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] welds the internal armor layer to [parent].</span>", "<span class='notice'>You weld the internal armor layer to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens the internal armor layer.</span>", "<span class='notice'>You unfasten the internal armor layer.</span>")
if(20)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] installs [I] to [parent].</span>", "<span class='notice'>You install [I] to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] cuts the internal armor layer from [parent].</span>", "<span class='notice'>You cut the internal armor layer from [parent].</span>")
if(21)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] secures Savannah-Ivanov Armor Plates.</span>", "<span class='notice'>You secure Savannah-Ivanov Armor Plates.</span>")
else
user.visible_message("<span class='notice'>[user] pries Savannah-Ivanov Armor Plates from [parent].</span>", "<span class='notice'>You pry Savannah-Ivanov Armor Plates from [parent].</span>")
if(22)
if(diff==FORWARD)
user.visible_message("<span class='notice'>[user] welds Savannah-Ivanov Armor Plates to [parent].</span>", "<span class='notice'>You weld Savannah-Ivanov Armor Plates to [parent].</span>")
else
user.visible_message("<span class='notice'>[user] unfastens Savannah-Ivanov Armor Plates.</span>", "<span class='notice'>You unfasten Savannah-Ivanov Armor Plates.</span>")
return TRUE
//ODYSSEUS
/datum/component/construction/unordered/mecha_chassis/odysseus
@@ -291,6 +291,46 @@
desc="Phazon armor plates. They are layered with plasma to protect the pilot from the stress of phasing and have unusual properties."
icon_state = "phazon_armor"
// Savannah-Ivanov
/obj/item/mecha_parts/chassis/savannah_ivanov
name = "\improper Savannah-Ivanov chassis"
construct_type = /datum/component/construction/unordered/mecha_chassis/savannah_ivanov
/obj/item/mecha_parts/part/savannah_ivanov_torso
name="\improper Savannah-Ivanov torso"
desc="A Savannah-Ivanov torso part. It's missing a huge chunk of space..."
icon_state = "savannah_ivanov_harness"
/obj/item/mecha_parts/part/savannah_ivanov_head
name="\improper Savannah-Ivanov head"
desc="A Savannah-Ivanov head. It's sensors have been adjusted to support graceful landings."
icon_state = "savannah_ivanov_head"
/obj/item/mecha_parts/part/savannah_ivanov_left_arm
name="\improper Savannah-Ivanov left arm"
desc="A Savannah-Ivanov left arm. Hidden rocket fabrication included in the wrists."
icon_state = "savannah_ivanov_l_arm"
/obj/item/mecha_parts/part/savannah_ivanov_right_arm
name="\improper Savannah-Ivanov right arm"
desc="A Savannah-Ivanov left arm. Hidden rocket fabrication included in the wrists."
icon_state = "savannah_ivanov_r_arm"
/obj/item/mecha_parts/part/savannah_ivanov_left_leg
name="\improper Savannah-Ivanov left leg"
desc="A Savannah-Ivanov left leg. In production they were designed to carry more than two passengers, so the leaping functionality was added as to not waste potential."
icon_state = "savannah_ivanov_l_leg"
/obj/item/mecha_parts/part/savannah_ivanov_right_leg
name="\improper Savannah-Ivanov right leg"
desc="A Savannah-Ivanov left leg. In production they were designed to carry more than two passengers, so the leaping functionality was added as to not waste potential."
icon_state = "savannah_ivanov_r_leg"
/obj/item/mecha_parts/part/savannah_ivanov_armor
name="Savannah-Ivanov armor"
desc="Savannah-Ivanov armor plates. They are uniquely shaped and reinforced to deal with the stresses of two pilots, grandiose leaps, and missiles."
icon_state = "savannah_ivanov_armor"
///////// Circuitboards
@@ -379,3 +419,15 @@
/obj/item/circuitboard/mecha/clarke/main
name = "Clarke Central Control module (Exosuit Board)"
icon_state = "mainboard"
/obj/item/circuitboard/mecha/savannah_ivanov/peripherals
name = "Savannah Peripherals Control module (Exosuit Board)"
icon_state = "mcontroller"
/obj/item/circuitboard/mecha/savannah_ivanov/targeting
name = "Ivanov Weapon Control and Targeting module (Exosuit Board)"
icon_state = "mcontroller"
/obj/item/circuitboard/mecha/savannah_ivanov/main
name = "Savannah-Ivanov Combination Control Lock module (Exosuit Board)"
icon_state = "mainboard"
+11 -1
View File
@@ -207,7 +207,17 @@
/obj/item/mecha_parts/part/phazon_left_leg,
/obj/item/mecha_parts/part/phazon_right_leg)
/obj/structure/mecha_wreckage/savannah_ivanov
name = "\improper Savannah-Ivanov wreckage"
icon = 'icons/mecha/coop_mech.dmi'
icon_state = "savannah_ivanov-broken"
parts = list(
/obj/item/mecha_parts/part/savannah_ivanov_torso,
/obj/item/mecha_parts/part/savannah_ivanov_head,
/obj/item/mecha_parts/part/savannah_ivanov_left_arm,
/obj/item/mecha_parts/part/savannah_ivanov_right_arm,
/obj/item/mecha_parts/part/savannah_ivanov_left_leg,
/obj/item/mecha_parts/part/savannah_ivanov_right_leg)
/obj/structure/mecha_wreckage/odysseus
name = "\improper Odysseus wreckage"
+85 -17
View File
@@ -1,7 +1,23 @@
//VEHICLE DEFAULT HANDLING
/**
* ## generate_actions
*
* You override this with initialize_passenger_action_type and initialize_controller_action_type calls
* To give passengers actions when they enter the vehicle.
* Read the documentation on the aforementioned procs to learn the difference
*/
/obj/vehicle/proc/generate_actions()
return
/**
* ## generate_action_type
*
* A small proc to properly set up each action path.
* args:
* * actiontype: typepath of the action the proc sets up.
* returns created and set up action instance
*/
/obj/vehicle/proc/generate_action_type(actiontype)
var/datum/action/vehicle/A = new actiontype
if(!istype(A))
@@ -9,45 +25,97 @@
A.vehicle_target = src
return A
/**
* ## initialize_passenger_action_type
*
* Gives any passenger that enters the mech this action.
* They will lose it when they disembark.
* args:
* * actiontype: typepath of the action you want to give occupants.
*/
/obj/vehicle/proc/initialize_passenger_action_type(actiontype)
autogrant_actions_passenger += actiontype
for(var/i in occupants)
grant_passenger_actions(i) //refresh
/**
* ## initialize_controller_action_type
*
* Gives any passenger that enters the mech this action... IF they have the correct vehicle control flag.
* This is used so passengers cannot press buttons only drivers should have, for example.
* args:
* * actiontype: typepath of the action you want to give occupants.
*/
/obj/vehicle/proc/initialize_controller_action_type(actiontype, control_flag)
LAZYINITLIST(autogrant_actions_controller["[control_flag]"])
autogrant_actions_controller["[control_flag]"] += actiontype
for(var/i in occupants)
grant_controller_actions(i) //refresh
/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/m)
if(isnull(LAZYACCESS(occupants, m)) || !actiontype)
/**
* ## grant_action_type_to_mob
*
* As on the tin, it does all the annoying small stuff and sanity needed
* to GRANT an action to a mob.
* args:
* * actiontype: typepath of the action you want to give to grant_to.
* * grant_to: the mob we're giving actiontype to
* returns TRUE if successfully granted
*/
/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/grant_to)
if(isnull(LAZYACCESS(occupants, grant_to)) || !actiontype)
return FALSE
LAZYINITLIST(occupant_actions[m])
if(occupant_actions[m][actiontype])
LAZYINITLIST(occupant_actions[grant_to])
if(occupant_actions[grant_to][actiontype])
return TRUE
var/datum/action/action = generate_action_type(actiontype)
action.Grant(m)
occupant_actions[m][action.type] = action
action.Grant(grant_to)
occupant_actions[grant_to][action.type] = action
return TRUE
/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/m)
if(isnull(LAZYACCESS(occupants, m)) || !actiontype)
/**
* ## remove_action_type_from_mob
*
* As on the tin, it does all the annoying small stuff and sanity needed
* to REMOVE an action to a mob.
* args:
* * actiontype: typepath of the action you want to give to grant_to.
* * take_from: the mob we're taking actiontype to
* returns TRUE if successfully removed
*/
/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/take_from)
if(isnull(LAZYACCESS(occupants, take_from)) || !actiontype)
return FALSE
LAZYINITLIST(occupant_actions[m])
if(occupant_actions[m][actiontype])
var/datum/action/action = occupant_actions[m][actiontype]
action.Remove(m)
occupant_actions[m] -= actiontype
LAZYINITLIST(occupant_actions[take_from])
if(occupant_actions[take_from][actiontype])
var/datum/action/action = occupant_actions[take_from][actiontype]
action.Remove(take_from)
occupant_actions[take_from] -= actiontype
return TRUE
/obj/vehicle/proc/grant_passenger_actions(mob/M)
/**
* ## grant_passenger_actions
*
* Called on every passenger that enters the vehicle, goes through the list of actions it needs to give...
* and does that.
* args:
* * grant_to: mob that needs to get every action the vehicle grants
*/
/obj/vehicle/proc/grant_passenger_actions(mob/grant_to)
for(var/v in autogrant_actions_passenger)
grant_action_type_to_mob(v, M)
grant_action_type_to_mob(v, grant_to)
/obj/vehicle/proc/remove_passenger_actions(mob/M)
/**
* ## remove_passenger_actions
*
* Called on every passenger that exits the vehicle, goes through the list of actions it needs to remove...
* and does that.
* args:
* * take_from: mob that needs to get every action the vehicle grants
*/
/obj/vehicle/proc/remove_passenger_actions(mob/take_from)
for(var/v in autogrant_actions_passenger)
remove_action_type_from_mob(v, M)
remove_action_type_from_mob(v, take_from)
/obj/vehicle/proc/grant_controller_actions(mob/M)
if(!istype(M) || isnull(LAZYACCESS(occupants, M)))
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 MiB

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.
+1
View File
@@ -3542,6 +3542,7 @@
#include "code\modules\vehicles\mecha\combat\marauder.dm"
#include "code\modules\vehicles\mecha\combat\phazon.dm"
#include "code\modules\vehicles\mecha\combat\reticence.dm"
#include "code\modules\vehicles\mecha\combat\savannah_ivanov.dm"
#include "code\modules\vehicles\mecha\equipment\mecha_equipment.dm"
#include "code\modules\vehicles\mecha\equipment\tools\medical_tools.dm"
#include "code\modules\vehicles\mecha\equipment\tools\mining_tools.dm"