293 lines
8.6 KiB
Plaintext
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
|