Divergent/mods/Powered Exo-Skeletons/gamedata/scripts/exo_powers.script

293 lines
8.6 KiB
Plaintext

local last_click = nil
local send_tip = news_manager.send_tip
local gc = game.translate_string
local is_exo = item_exo_device.is_exo
local get_data = item_exo_device.get_data
local set_data = item_exo_device.set_data
local init_data = item_exo_device.init_data
local print_dbg = item_exo_device.print_dbg
local effect = particles_object("artefact\\effects\\af_electra_show_flash_00")
local st = {}
local ini_powers = ini_file("items\\settings\\exo_power_cfg.ltx")
-- assemble the sound object tables ahead of time
function build_sound_tables()
ini_powers:section_for_each(function(section)
printf("Building sound table for %s", section)
st[section] = {}
st[section][1] = sound_object(ini_powers:r_string_ex(section, "snd_windup"))
st[section][2] = sound_object(ini_powers:r_string_ex(section, "snd_duration"))
st[section][3] = sound_object(ini_powers:r_string_ex(section, "snd_cooldown"))
end)
end
local function on_key_press(key)
local inventory = GetActorMenu()
if (inventory and inventory:IsShown()) then
return
end
local bind = dik_to_bind(key)
if bind == 7 then
-- print_dbg("Pressed sprint")
local tg = time_global()
if not last_click then
last_click = tg
else
if tg < last_click + 400 then
activate_powers()
end
last_click = nil
end
end
end
function activate_speed()
speed.add_speed("gotta_go_Fast", 1.5, false)
send_tip(db.actor, gc("st_act_sprint"), nil, "swiss_knife", 6000)
level.add_pp_effector("electra.ppe", 6969, true)
-- electra ppe
end
function deactivate_speed()
speed.remove_speed("gotta_go_Fast")
level.remove_pp_effector(6969)
end
local armored = false
function activate_tank()
send_tip(db.actor, gc("st_act_tank"), nil, "swiss_knife", 6000)
speed.add_speed("gotta_go_Fast", 0.8, false)
level.add_pp_effector("blur.ppe", 6969, true)
armored = true
end
function deactivate_tank()
speed.remove_speed("gotta_go_Fast")
level.remove_pp_effector(6969)
armored = false
end
-- Haruwu
local radius = 10
local blast_particles = {particles_object("amik\\anomaly\\electra\\electra2_sparks"), particles_object("amik\\anomaly\\electra\\electra_dust_distort")}
local blast_sounds = {sound_object("device\\bridge\\motor_start"), sound_object("anomaly\\electra_blast"), sound_object("device\\bridge\\motor_stop")}
function activate_blast()
-- blast_sounds[1]:play(db.actor, 0, sound_object.s2d)
-- CreateTimeEvent("execute_blast_haruka", "execute_blast_haruka", blast_sounds[1]:length() / 1000, blast)
blast()
end
function blast()
local pos = db.actor:position()
local h = hit()
local exosuit = db.actor:item_in_slot(7)
local id = exosuit:id()
local data = get_data(id)
if not data then
data = init_data(id)
end
h.type = hit.shock
h.draftsman = db.actor
h.power = 1.5
h.bone = "bip01_spine"
level.add_pp_effector("blink.ppe", 6969, false)
level.set_pp_effector_factor(6969, 0.1)
blast_sounds[2]:play(db.actor, 0, sound_object.s2d)
blast_particles[1]:play_at_pos(pos)
blast_particles[2]:play_at_pos(pos)
level.iterate_nearest(pos, radius, function(obj)
if data.power < 30 then return true end
if obj and obj:alive() and obj:id() ~= AC_ID then
obj:hit(h)
effect:play_at_pos(obj:position())
data.power = data.power - 2 -- remove 2 charge for each hit
end
end)
-- CreateTimeEvent("play_end_sfx_haruka", "play_end_sfx_haruka", blast_sounds[2]:length() / 2000, function()
-- blast_sounds[3]:play(db.actor, 0, sound_object.s2d)
-- return true
-- end)
set_data(id, data)
return true
end
function deactivate_blast()
return
end
function exec(str)
-- ui_inventory lololol
if str then
str = str_explode(str,"%.") -- dot needs escape character!
if str[1] and str[2] and _G[ str[1] ] and _G[ str[1] ][ str[2] ] then
_G[ str[1] ][ str[2] ](obj)
else
print_dbg("Could not exec function %s", str)
end
end
end
local current_outfit
local start_time
local DURATION = 8000
local COOLDOWN = 20
local on_cooldown = false
local power_active = false
local active_power
function activate_powers()
if on_cooldown or power_active ~= false then
-- cooling down
send_tip(db.actor, gc("st_err_cooldown"), nil, "swiss_knife", 6000)
return
end
local exosuit = db.actor:item_in_slot(7)
if exosuit and is_exo(exosuit) then
local id = exosuit:id()
local sec = exosuit:section()
local data = get_data(id)
if not data then
data = init_data(id)
end
print_dbg("equipped power: %s", data.supply and data.supply.ability or "none")
if not data.supply then return end
if not data.supply.ability or not ini_powers:section_exist(data.supply.ability) then
send_tip(db.actor, gc("st_err_none"), nil, "swiss_knife", 6000)
return
end
local drain = ini_powers:r_float_ex(data.supply.ability, "power_cost") or 20
if data.power < drain + 10 then
-- insufficient power
send_tip(db.actor, gc("st_err_power"), nil, "swiss_knife", 6000)
return
end
data.power = clamp(data.power - drain, 0, 400)
set_data(id, data)
power_active = data.supply.ability
sounds = st[power_active]
start_time = time_global()
print_dbg("saved tg %s", start_time)
current_outfit = id
local duration = (ini_powers:r_float_ex(data.supply.ability, "power_duration") * 1000) or DURATION
local cooldown = ini_powers:r_float_ex(data.supply.ability, "power_cooldown") or COOLDOWN
local delay = sounds[1]:length() / 1000
sounds[1]:play(db.actor, 0, sound_object.s2d)
-- if power_active ~= "recharge" then
-- end
CreateTimeEvent("exo_powers", "activate_powers", delay, maintain_power, duration, cooldown)
end
end
-- continually run and watch for outfit changes
function maintain_power(duration, cooldown)
local id = db.actor:item_in_slot(7) and db.actor:item_in_slot(7):id() or 0
-- there should be a better way to do this i think
if not st[power_active][2]:playing() then
print_dbg("start activate power")
exec(ini_powers:r_string_ex(power_active, "power_start"))
st[power_active][2]:play(db.actor, 0, sound_object.s2d)
end
if id ~= current_outfit then
print_dbg("bruh you switched")
deactivate_powers(cooldown)
return true
end
if time_global() > start_time + duration then
print_dbg("time's up")
deactivate_powers(cooldown)
return true
end
return false
end
function deactivate_powers(cooldown)
exec(ini_powers:r_string_ex(power_active, "power_end"))
if st[power_active][2]:playing() then
st[power_active][2]:stop()
end
st[power_active][3]:play(db.actor, 0, sound_object.s2d)
power_active = false
on_cooldown = true
CreateTimeEvent("exo_powers", "deactivate_power", cooldown, reset_cooldown)
end
function reset_cooldown()
on_cooldown = false
send_tip(db.actor, gc("st_ok_cooldown"), nil, "swiss_knife", 6000)
return true
end
function actor_on_before_hit(s_hit)
if not (s_hit.type == hit.wound or s_hit.type == hit.fire_wound) then return end
if armored then
if s_hit.type == hit.fire_wound then
s_hit.power = s_hit.power / 2
end
if s_hit.type == hit.wound then
s_hit.power = s_hit.power / 10
end
end
end
local function ram()
if IsMoveState("mcSprint") and power_active == "sprint" then
local obj = level.get_target_obj()
local dist = level.get_target_dist()
if not obj or not (IsStalker(obj) or IsMonster(obj)) or dist > 2.1 then return end
local actor = db.actor
local suit = db.actor:item_in_slot(7)
local is_rhino = suit and string.find(suit:section(), "nosorog") or false
local h = hit()
h.type = hit.strike
h.draftsman = actor
h.power = is_rhino and 1 or 0.6
h.bone = "bip01_spine"
level.add_cam_effector("camera_effects\\hit_front.anm", 5923, false, "")
level.add_pp_effector("bloody.ppe", 9230, false)
level.set_pp_effector_factor(9230, 0.2)
obj:hit(h)
print_dbg("BONK")
end
end
function actor_on_footstep(material, power, hud_view, flags)
if not power_active then return end
ram()
effect:play_at_pos(db.actor:position())
end
function on_game_start()
RegisterScriptCallback("actor_on_footstep", actor_on_footstep)
build_sound_tables()
end