Added New Mods and Profiles Folders

This is a complete rebuild of the modpack, with all new mods and updates for 1.5.3 of Anomaly.
This commit is contained in:
2025-01-14 05:07:53 -05:00
parent 85c665b107
commit 376b4b9689
21217 changed files with 546254 additions and 0 deletions
@@ -0,0 +1,99 @@
--[[Utils_Ui.script
The vanilla Reinit() attempted to sort the arrays by default which caused some issues with
the display of mutant loot when the amount increased in the window. I've made the no-sorting
an optional feature instead of the default. This is only called during mutant looting anyway,
but better safe than sorry.]]
function utils_ui.UICellContainer:Reinit(t, tf, nosort)
self:Reset()
-- If no inventory is passed, this function will just clear cells
if (not t) then
return
end
-- Create cells
self.ignore_scroll = true
self:Print(nil, "Reset | START Number of cells: %s", #self.cell)
local sort_order = self:GetSortMethod()
if(nosort) then
if self.showcase then
for i,sec in pairs(t) do
self:AddItem(nil,sec, tf and tf[i])
end
else
for i,obj in pairs(t) do
self:AddItem(obj, nil, tf and tf[i])
end
end
else
if self.showcase then
for i,sec in spairs(t, sort_order) do
self:AddItem(nil,sec, tf and tf[i])
end
else
for i,obj in spairs(t, sort_order) do
self:AddItem(obj, nil, tf and tf[i])
end
end
end
self.ignore_scroll = false
self:Print(nil, "Reset | END Number of cells: %s", #self.cell)
self:Scroll_Reinit()
end
--[[bind_crow.script
Vanilla update() used a flawed method that would always return false and prevent crows
from being lootable at all. It also was significalty less robust than Faustle's updated
bind_monster update() function, but was checking all the exact same things so I simply
ported it over. Considering my mod would have made existing fixes to crow looting
fail I implemented it myself.]]
function bind_crow.crow_binder:update(delta)
-- standart update
object_binder.update(self, delta)
if not (self.object:alive()) then
if (self.body_timer<=time_global()-120000) and (self.body_timer~=0) then
printf("releasing object ["..self.object:name().."]")
local se_obj = alife_object(self.object:id())
if (se_obj) then
safe_release_manager.release(se_obj)
end
end
--Alundaio
-- By Faustle - Cloned over from bind_monster.script with minimial edits-tB
if not (self.object:alive()) then
local looted = se_load_var(self.object:id(),self.object:name(),"looted")
if (not looted) then
if (item_knife.is_equipped()) then
if (item_knife.get_condition() < 0.15) then
self.object:set_callback(callback.use_object, nil)
self.object:set_tip_text(game.translate_string("st_body_knife_bad"))
return
end
if (not item_knife.can_loot(self.object:section())) then
self.object:set_callback(callback.use_object, nil)
self.object:set_tip_text(game.translate_string("st_body_knife_weak"))
else
self.object:set_callback(callback.use_object, self.use_callback, self)
self.object:set_tip_text(game.translate_string("st_body_loot"))
end
else
self.object:set_callback(callback.use_object, nil)
self.object:set_tip_text(game.translate_string("st_body_knife_needed"))
return
end
else
self.object:set_callback(callback.use_object, nil)
self.object:set_tip_text("")
end
return
end
--
--Alundaio
end
end
@@ -0,0 +1,36 @@
function on_mcm_load()
op = {id= "tb_HuntKit",gr={
{id="tb_HuntKit_settings",sh=true,gr={
{id="header", type="slide", link="tb_HuntKit_MCMHeader", text="tB's Hunter's Kit - A Butchery Engine", size={563,50}, spacing=20},
{type="title", align="l", text="Mod Compatibility - (Hover setting names for details)"},
{id="muteHarvestSounds", type="check", val=1, def=false},
{id="useHarvestSoundFallback", type="check", val=1, def=false},
{id="disableExtraSounds", type="check",val=1, def=false},
{type="line"},
{type="title", align="l", text="Customization - (Hover setting names for details)"},
{type="desc", align="c", text="It is highly advised you leave these options at their defaults. No perminant damage can occur to your saves so feel free to experiment, but alterations may cause balancing issues at any difficulty. This system is complex and scales itself. I spent hours ensuring balance of the default settings were nearest to ideal as possible so you could just install and play, but of course I can't account for everything. In the end, whatever you think is most fun is always best setting -trashBattery"},
{id="harvestHardcap", type = "track", val=2, min=1, max=100, step=1, def=92},
{id="minItems", type="input", val=2, min=-9999, max=9999, def=1},
{id="harvestDifficulty", type="input", val=2, min=-9999, max=9999, def=1},
{id="scavengeDifficulty", type="input", val=2, min=-9999, max=9999, def=1}
}
},
{id="tb_HuntKit_features",sh=true,gr={
{id="header", type="slide", link="tb_HuntKit_MCMHeader", text="tB's Hunter's Kit - A Butchery Engine", size={563,50}, spacing=20},
{type="title", align="l", text="Hunter's Kit"},
{type="desc",text="%c[d_green]•%c[d_white] It works when not worn, but is quite heavy. If you don't wear it it'll take up significant space. \\n%c[d_green]•%c[d_white] While wearing it, the carry bonus offsets the weight and gives you similar storage to the Camping Backpack. \\n%c[d_green]•%c[d_white] The Hunter's Kit is craftable using logical items you could realistically obtain. No more random endgame materials to make one. \\n%c[d_red]• The gameplay setting to require the kit to be worn is now ignored."},
{type="title", align="l", text="Mutant Loot"},
{type="desc",text="%c[d_green]•%c[d_white] Mutants now drop an amount of meat respective to their fleshy mass, not their difficulty. Fleshes are great sources of low-quality food now. Even birds have something to eat, however it won't be much.\\n%c[d_green]•%c[d_white] Mutants that drop things other than meat are unaffected by the Hunter's Kit. No increased chances to find money or porno mags just because you had some proper knives on you.\\n%c[d_green]•%c[d_white] Birds are now harvestable! They were always intended to be, but a bug in the crow_binder script was causing issues and has been fixed."},
{type="title", align="l", text="Variable Harvest Animation Speeds"},
{type="desc",text="%c[d_green]•%c[d_white] There are 3 harvesting speeds. Fast, Normal, Slow \\n%c[d_green]•%c[d_white] Harvesting without the backpack is Normal. \\n%c[d_green]•%c[d_white] Harvesting with the backpack is Slow, implying you are using your tools and taking time to gather more. \\n%c[d_green]•%c[d_white] Having the \"Well Dressed\" achievement increases harvesting speeds Without/With to Fast/Normal, respectively. \\n%c[d_red]• If you are using FDDA make sure you have the correct option enabled in this mod."},
{type="title", align="l", text="Reintroduced Harvesting Sounds"},
{type="desc",text="%c[d_green]•%c[d_white] The game has 9 different harvesting effects that were intended for each type of creature, but only 1 was ever implemented. \\n%c[d_green]•%c[d_white] The sounds are all generic bone/meat cutting noises so now I have the game select them at random for variance. \\n%c[d_green]•%c[d_white] This can be disabled in the options if you like."},
{type="line"},
{type="title", align="l", text="%c[d_orange]Version - 1.0"}
}
}
}
}
return op
end
@@ -0,0 +1,722 @@
--[[
-----------------------------------
Copyright (C) 2012 Alundaio
This program is free software; you can redistribute and/or modify
it under the terms of the Open S.T.A.L.K.E.R. Mod License version 1.0.
-----------------------------------
ponney68
-----------------------------------
Tronex
Last edit: 2019/12/17
Added Loot all button, organized script, inventory cell system, alife spawn handlers
-----------------------------------
trashBattery (tB)
Last edit: 2024/10/23
Rewrote the logic for mutant loot handling to support new "percent of max" method and
removed the vanilla "magical duplication" methods. See readme for more info.
-]]
--Load Reserouces
local ini_mutant = ini_file_ex("items\\settings\\mutant_loot.ltx") --Using ini_file_ex now instead of utils_data:ini_file -tB
local ini_tbHuntKit_settings = ini_file_ex("tbHuntKit_settings.ltx") --Configs for the features added by tbHuntKit (this mod) -tB
local ini_actorFX = ini_file_ex("plugins\\actor_effects.ltx") --Need this for reading the anim data later -tB
--Load configs. Descriptions are in tbHuntKit_settings.ltx -tB
local envHardcap,envHarvestDiff,envScavengeDiff,envMinItems,disableExtraSounds,muteHarvestSounds,useHarvestSoundFallback
function loadConfigs() --Tied to "on_option_change" callback. -tB
if ui_mcm then
envHardcap = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/harvestHardcap")/100 or 0.92
envHarvestDiff = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/harvestDifficulty") or 1.00
envScavengeDiff = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/scavengeDifficulty") or 1.00
envMinItems = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/minItems") or 1.00
disableExtraSounds = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/disableExtraSounds") or false
muteHarvestSounds = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/muteHarvestSounds") or false
useHarvestSoundFallback = ui_mcm.get("tb_HuntKit/tb_HuntKit_settings/useHarvestSoundFallback") or false
printf("-ui_mutant_loot loaded configs from MCM")
else
envHardcap = ini_tbHuntKit_settings:r_float_ex("environment","harvestHardcap")/100 or 0.92
envHarvestDiff = ini_tbHuntKit_settings:r_float_ex("environment","harvestDifficulty") or 1.00
envScavengeDiff = ini_tbHuntKit_settings:r_float_ex("environment","scavengeDifficulty") or 1.00
envMinItems = ini_tbHuntKit_settings:r_float_ex("environment","minItems") or 1.00
disableExtraSounds = ini_tbHuntKit_settings:r_bool_ex("compatiblity","disableExtraSounds") or false
muteHarvestSounds = ini_tbHuntKit_settings:r_bool_ex("compatiblity","muteHarvestSounds") or false
useHarvestSoundFallback = ini_tbHuntKit_settings:r_bool_ex("compatiblity","useHarvestSoundFallback") or false
printf("-ui_mutant_loot loaded configs from tbHuntKit_settings.ltx")
end
end
loadConfigs()
--The game came with 9 sounds for harvesting and only ever uses 1?! Let's use them all (or not if you disable them) :D -tB
local harvestSFX = {
"inv_mutant_loot_animal",
"inv_mutant_loot_animal2",
"inv_mutant_loot_crow",
"inv_mutant_loot_grease",
"inv_mutant_loot_grease2",
"inv_mutant_loot_human",
"inv_mutant_loot_human2",
"inv_mutant_loot_rotten",
"inv_mutant_loot_smaller"
}
--Extract creature whitelist. -tB
local validCreatures = {}
local forIncr = 0
for k in pairs(ini_mutant:collect_section("whitelist")) do
forIncr=forIncr+1
validCreatures[forIncr]=k
end
local sec_kit_hunt = "kit_hunt"
local item_prop_table = { cond_r = {30,70} , cond_ct = "part" , cond_cr = {0.5,0.75,1} }
-- Loot Mutant
local MutantLootDecayTime = ini_mutant:r_float_ex("mutant_loot_mod","decay_time") or 7200
local kind_to_section = {
["SM_KARLIK"] = "karlik",
["SM_PSYSUCKER"] = "psysucker",
["SM_LURKER"] = "lurker"
}
local clsid_to_section = {
[clsid.bloodsucker_s] = "bloodsucker",
[clsid.boar_s] = "boar",
[clsid.burer_s] = "burer",
[clsid.chimera_s] = "chimera",
[clsid.controller_s] = "controller",
[clsid.dog_s] = "dog",
[clsid.flesh_s] = "flesh",
[clsid.gigant_s] = "gigant",
[clsid.poltergeist_s] = "poltergeist",
[clsid.psy_dog_s] = "psy_dog",
[clsid.psy_dog_phantom_s] = "psy_dog",
[clsid.pseudodog_s] = "pseudodog",
[clsid.snork_s] = "snork",
[clsid.tushkano_s] = "tushkano",
[clsid.cat_s] = "cat",
[clsid.fracture_s] = "fracture",
[clsid.zombie_s] = "zombie",
[clsid.crow] = "crow",
[clsid.rat_s] = "rat"
}
local clsdbg_to_section = {
["SM_KARLIK"] = "karlik",
["SM_PSYSUCKER"] = "psysucker",
["SM_LURKER"] = "lurker"
}
local killed_mutant_tbl = { -- ponney68: This table based on "species" of mutants
-- TRX: A-Life Revamp
psysucker = {file="ui\\ui_actor_monsters_pda_3",x="393",y="0",type="small"},
lurker = {file="ui\\ui_actor_monsters_pda_3",x="0",y="0",type="small"},
karlik = {file="ui\\ui_actor_monsters_pda_3",x="0",y="200",type="small"},
snork = {file="ui\\ui_actor_monsters_pda",x="393",y="0",type="small"},
dog = {file="ui\\ui_actor_monsters_pda",x="0",y="800",type="small"},
pseudodog = {file="ui\\ui_actor_monsters_pda",x="393",y="200",type="small"},
psy_dog = {file="ui\\ui_actor_monsters_pda",x="393",y="200",type="small"},
poltergeist = {file="ui\\ui_actor_monsters_pda",x="0",y="400",type="small"},
bloodsucker = {file="ui\\ui_actor_monsters_pda",x="393",y="400",type="human"},
controller = {file="ui\\ui_actor_monsters_pda",x="393",y="800",type="human"},
chimera = {file="ui\\ui_actor_monsters_pda",x="0",y="600",type="large"},
tushkano = {file="ui\\ui_actor_monsters_pda",x="0",y="0",type="small"},
rat = {file="ui\\ui_actor_monsters_pda",x="0",y="0",type="small"},
flesh = {file="ui\\ui_actor_monsters_pda",x="393",y="600",type="large"},
tark = {file="ui\\ui_actor_monsters_pda_2",x="0",y="0",type="human"},
rotan = {file="ui\\ui_actor_monsters_pda",x="0",y="0",type="human"},
burer = {file="ui\\ui_actor_monsters_pda_1",x="0",y="0",type="large"},
boar = {file="ui\\ui_actor_monsters_pda_1",x="393",y="0",type="large"},
giant = {file="ui\\ui_actor_monsters_pda_1",x="0",y="200",type="large"},
cat = {file="ui\\ui_actor_monsters_pda_2",x="0",y="0",type="small"},
fracture = {file="ui\\ui_actor_monsters_pda_2",x="393",y="200",type="human"},
bird = {file="ui\\ui_actor_monsters_pda_2",x="393",y="0",type="small"},
zombie = {file="ui\\ui_actor_monsters_pda_2",x="0",y="200",type="human"},
bloodsucker_arena = {file="ui\\ui_actor_monsters_pda",x="393",y="400",type="human"},
burer_arena = {file="ui\\ui_actor_monsters_pda_1",x="0",y="0",type="large"},
pseudodog_arena = {file="ui\\ui_actor_monsters_pda",x="393",y="200",type="small"},
snork_arena = {file="ui\\ui_actor_monsters_pda",x="393",y="0",type="human"},
}
function check_hunterKit(useNeedsEquipped) --Replaces "is_huntkit" variable with a more versitile function. Ignores the game option by default. The option is redundant due to the new design. -tB
local actor = db.actor
local backpack = actor:item_in_slot(13)
local needs_equipped_hk = false
if useNeedsEquipped then
needs_equipped_hk = ui_options.get("gameplay/general/need_equipped_hkit")
end
if ((needs_equipped_hk and backpack == sec_kit_hunt) or (not needs_equipped_hk and actor:object(sec_kit_hunt))) then
return true
end
return false
end
function actor_effects_getAnimLen(name) --actor_effects.ltx uses a non-standard method of animation formatting so I have to do this -tB
local kMax = 0
for k in pairs(ini_actorFX:collect_section(name)) do
k = tonumber(k)
kMax = k>kMax and k or kMax
end
return kMax
end
function play_harvestAnim(override) --Play the correct harvesting animation based on the state of the player. Return animation time in seconds. -tB
local boost,anim
if (actor_effects) then
if override then
boost = override
else
boost = (game_achievements.has_achievement("well_dressed") and 1 or 0) + (check_hunterKit() and 0 or 1)
end
if (boost >= 2) then
anim = "mutant_looting_boost_2"
elseif (boost == 1) then
anim = "mutant_looting_boost_1"
else
anim = "mutant_looting"
end
end
actor_effects.play_item_fx(anim)
return actor_effects_getAnimLen(anim)/1000
end
function loot_mutant(section, clsid, loot_table, npc, dont_create, victim) -- Prepare mutant loot
npc = npc or db.actor
local clsid = clsid or obj and obj:clsid()
local kind = section and ini_sys:r_string_ex(section,"kind") or "unknown"
if not (clsid) then
return
end
local loot, sec, count
local str_explode = str_explode
local mutant = clsdbg_to_section[kind] or clsid_to_section[clsid]
--Creating possible_items{} using ini_file_ex from _g instead of the old utils_data method. -tB
local possible_items = {}
forIncr=0
for k in pairs(ini_mutant:collect_section(mutant)) do
forIncr=forIncr+1
possible_items[forIncr]=k
end
local sim = alife()
local npc_id = npc and npc:id()
local npc_pos = npc and npc:position()
local npc_lvl_id = npc and npc:level_vertex_id()
local npc_game_id = npc and npc:game_vertex_id()
--Check if the looted creature is part of the whitelist. -tB
local isCreature = false
for i=1,#validCreatures do
if mutant == validCreatures[i] then
isCreature = true
break
end
end
-- Spawn items on NPC if he looted the mutant
for i=1,#possible_items do
local chance
local chanceFloor = envMinItems-1 --Min # of items to drop before scaling takes effect. Using #-1 felt better for configs.-tB
local chanceExp = 1
local flatChance = false
loot = str_explode(possible_items[i],",")
sec = tostring(loot[1])
count = tonumber(loot[2])
if not count then
printf("ui_mutant_loot.loot_mutant() >> Unacceptable quantity of loot item ["..sec.."]")
count = 0
end
--Check if an override chance was set. If so, use vanilla linear probability. Backpack doubles chances. -tB
if loot[3] then
flatChance = true
chance = tonumber(loot[3]) or 1
if (isCreature and (string.match(sec, '^mutant_part_') or (string.match(sec, '^hide_')))) then
if(check_hunterKit()) then
chance = chance*2*envHarvestDiff
else
chance = chance*envScavengeDiff
end
end
else
--Otherwise, configure probability curve. -tB
if (isCreature and (string.match(sec, '^mutant_part_') or (string.match(sec, '^hide_')))) then
if(check_hunterKit()) then
chanceExp = 0.5*(1/(envHarvestDiff+0.001))
else
chanceExp = 2.2*(1/(envScavengeDiff+0.001))
end
end
chanceFloor = chanceFloor + math.floor(count*0.1)
end
for i=1,count do
if not flatChance then
if i < chanceFloor then
chance = 1
else
chance = (1/(i-chanceFloor))^chanceExp
end
end
if chance > envHardcap then chance = envHardcap end
if (math.random() <= chance) then
-- In case we don't want to bother with loot table
local se_obj
if (not dont_create) then
se_obj = alife_create_item(sec, npc, item_prop_table)
end
-- Fill loot table if needed
if (loot_table) then
local sec_d, uses = utils_item.get_defined_uses(sec)
if (not loot_table[sec_d]) then
loot_table[sec_d] = {}
end
local c = loot_table[sec_d].count
c = c and (c + 1) or 1
loot_table[sec_d].count = c
if se_obj then
loot_table[sec_d][c] = se_obj.id
end
--printf("loot_mutant")
--[[
if npc and npc:id() ~= AC_ID then
se_obj = alife_create_item(sec, npc, item_prop_table)
end
--]]
end
end
end
end
-- Unlock relevant mutant article in guide.
if mutant and npc and (npc:id() == AC_ID) then
SendScriptCallback("actor_on_interaction", "mutants", nil, mutant)
end
SendScriptCallback("monster_on_loot_init",victim,loot_table)
end
----------------------------------------------------------------------
GUI = nil -- instance, don't touch
function start(obj, for_bug1, for_bug2)
if (not obj) then
printf("!ERROR ui_mutant_loot | no game object passed!")
return
end
if (not GUI) then
GUI = UIMutantLoot()
end
if (GUI) and (not GUI:IsShown()) then
local can_show = GUI:Reset(obj, for_bug1, for_bug2)
if can_show then
GUI:ShowDialog(true)
Register_UI("UIMutantLoot","ui_mutant_loot")
end
end
end
function start_CreateTimeEvent(obj, for_bug1, for_bug2)
level.enable_input()
start(obj, for_bug1, for_bug2)
return true
end
----------------------------------------------------------------------
-- CALLBACKS
----------------------------------------------------------------------
function monster_on_actor_use_callback(obj,who) -- Open mutant loot UI
-- Return if mutant is already looted
local looted = se_load_var(obj:id(),obj:name(),"looted")
local firstTime = load_var(obj,"loot")
if (looted) then
return
end
se_save_var(obj:id(),obj:name(),"looted",true) --bind_crow.script updatates no longer require the old logic to check if it's a crow. -tB
-- This is important so NPCs don't try to loot the corpse the player is looting
xr_corpse_detection.set_valuable_loot(obj:id(),false)
-- if mutant corpse is lefted for long time, body is decayed
local st = db.storage[obj:id()]
if (st and st.death_time and game.get_game_time():diffSec(st.death_time) > MutantLootDecayTime) then
actor_menu.set_msg(1, game.translate_string("st_body_decayed"),4)
-- Start the Mutant Loot UI
else
--Play the harvest animation and sounds only the frist time the mutant is cut open. -tB
if not firstTime then
item_knife.degradate() --Damage the knife for the first cut into the creatutre. binder will damage further for each item removed. -tB
local aTime = play_harvestAnim()
if not muteHarvestSounds then
if disableExtraSounds then
if useHarvestSoundFallback then
xr_sound.set_sound_play(AC_ID,"inv_mutant_loot_animal2")
else
xr_sound.set_sound_play(AC_ID,"inv_mutant_loot_animal")
end
else
local harvestSFX_RND = harvestSFX[math.random(1,#harvestSFX)]
if harvestSFX_RND == "inv_mutant_loot_animal" and useHarvestSoundFallback then
harvestSFX_RND = "inv_mutant_loot_animal2"
end
xr_sound.set_sound_play(AC_ID,harvestSFX_RND)
end
else
end
level.disable_input()
CreateTimeEvent("UIML_HarvestAnim_e","UIML_HarvestAnim_a",aTime,start_CreateTimeEvent,obj, obj:id(), obj:section(), obj:clsid())
else
start(obj, obj:id(), obj:section(), obj:clsid())
end
end
end
function monster_on_loot_init(obj,t)
-- t['conserva'] = {
-- count = 3
-- }
-- utils_data.print_table(t,obj and obj:name() or "no_obj")
end
function on_game_start()
RegisterScriptCallback("monster_on_actor_use_callback",monster_on_actor_use_callback)
RegisterScriptCallback("monster_on_loot_init",monster_on_loot_init)
RegisterScriptCallback("on_option_change",loadConfigs)
end
----------------------------------------------------------------------
-- UI
----------------------------------------------------------------------
class "UIMutantLoot" (CUIScriptWnd)
function UIMutantLoot:__init() super()
self:InitControls()
self:InitCallBacks()
end
function UIMutantLoot:__finalize()
end
function UIMutantLoot:InitControls()
self:SetWndRect (Frect():set(0,0,1024,768))
self:SetAutoDelete(true)
self.xml = CScriptXmlInit()
self.xml:ParseFile ("ui_mutant_loot.xml")
local xml = self.xml
self.dialog = xml:InitStatic("mutant_loot:background",self)
-- Mutant image
self.image = self.xml:InitStatic("mutant_loot:image",self.dialog)
-- Loot
self.frame = xml:InitStatic("mutant_loot:frame",self.dialog)
self.CC = utils_ui.UICellContainer("loot", self, nil, "mutant_loot:cont_loot", self.dialog)
self.CC.showcase = true
-- self.CC.can_select = true
self.CC.disable_drag = true
self.CC.disable_stack = true
self.CC:SetGridSpecs(35, 2)
self.item_info = utils_ui.UIInfoItem(self, 1000)
-- Button Loot one
self.btn_loot_one = xml:Init3tButton("mutant_loot:btn_loot",self.dialog)
self:Register(self.btn_loot_one, "button_loot")
-- Button Loot all
self.btn_loot_all = xml:Init3tButton("mutant_loot:btn_loot_all",self.dialog)
self:Register(self.btn_loot_all, "button_loot_all")
-- Button Cancel
self.btn_cancel = xml:Init3tButton("mutant_loot:btn_cancel",self.dialog)
self:Register(self.btn_cancel, "button_cancel")
end
function UIMutantLoot:InitCallBacks()
self:AddCallback("button_loot",ui_events.BUTTON_CLICKED,self.OnButton_LootSelected,self)
self:AddCallback("button_loot_all",ui_events.BUTTON_CLICKED,self.OnButton_LootAll,self)
self:AddCallback("button_cancel",ui_events.BUTTON_CLICKED,self.Close,self)
end
function UIMutantLoot:Reset(obj, for_bug1, for_bug2)
local function is_number(var)
local function lets_try(var)
var = tonumber(var)
return (var > 0) or (var < 0) or var or -var
end
if pcall(function() lets_try(var) end) then
return true
else
return false
end
end
if not (is_number(obj)) then
self.section = obj:section()
self.clsid = obj:clsid()
self.id = obj:id()
self.obj = obj
else
self.id = obj
self.section=for_bug1
self.clsid = for_bug2
self.obj = nil
end
self:SetMutantImage()
return self:FillList()
end
function UIMutantLoot:Update()
CUIScriptWnd.Update(self)
-- Highlight selected items
for idx,ci in pairs(self.CC.cell) do
if (not ci:IsCursorOverWindow()) then
if ci.flags.selected then
ci:Highlight(true,"green")
else
ci:Highlight(false)
end
end
end
-- Updating item info box and item cell containers
local found_cell = self.CC:Update(self.item_info)
if (not found_cell) then
self.item_info:Update()
end
end
-- Utility
function UIMutantLoot:SetMutantImage()
local mutant_id = game.translate_string(ini_sys:r_string_ex(self.section,"species") or "")
local kind = ini_sys:r_string_ex(self.section,"kind") or "unknown"
mutant_id = kind_to_section[kind] or mutant_id
local mutant_f = "ui\\ui_actor_monsters_pda_1"
local mutant_x = 0
local mutant_y = 0
mutant_f = tostring(killed_mutant_tbl[mutant_id].file)
mutant_x = tostring(killed_mutant_tbl[mutant_id].x)
mutant_y = tostring(killed_mutant_tbl[mutant_id].y)
local x1 = mutant_x
local y1 = mutant_y
local mutant_width = 393
local mutant_height = 200
local x2 = x1 + mutant_width
local y2 = y1 + mutant_height
self.image:InitTexture(tostring(mutant_f))
self.image:SetTextureRect(Frect():set(x1,y1,x2,y2))
self.image:SetStretchTexture(true)
end
function UIMutantLoot:Loot(loot_all)
local obj_mutant = level.object_by_id(self.id)
if (not obj_mutant) then
self:Close()
return
end
local is_looted
local sim = alife()
local actor = db.actor
--[[Disable old magic hunter kit. I'm leaving this here in case anyone wants to know what it used to be. -tB
local backpack = actor:item_in_slot(13)
local is_huntkit
local needs_equipped_hk = ui_options.get("gameplay/general/need_equipped_hkit")
if (needs_equipped_hk and (backpack and (backpack:section() == sec_kit_hunt))) or (not needs_equipped_hk and db.actor:object(sec_kit_hunt)) then
is_huntkit = true
end
]]--
-- Spawn selected items, clean from loot table
if loot_all then
local tbl = self.loot -- temp
for sec,t in pairs(tbl) do
for i=1,t.count do
is_looted = true
item_knife.degradate()
alife_create_item(sec, db.actor, item_prop_table)
--[[Disable old magic hunter kit. -tB
if is_huntkit and (math.random(100) < bonus_part_chance) then
alife_create_item(sec, db.actor, item_prop_table)
end
]]--
self.loot[sec].count = self.loot[sec].count - 1
if (self.loot[sec].count == 0) then
self.loot[sec] = nil
end
end
end
else
for idx,ci in pairs(self.CC.cell) do
if ci.flags.selected then
local sec = ci.section
is_looted = true
item_knife.degradate()
alife_create_item(sec, db.actor, item_prop_table)
--[[Disable old magic hunter kit. -tB
if is_huntkit and (math.random(100) < bonus_part_chance) then
alife_create_item(sec, db.actor, item_prop_table)
end
]]--
self.loot[sec].count = self.loot[sec].count - 1
if self.loot[sec].count == 0 then
self.loot[sec] = nilt
end
end
end
end
-- If no item is looted, don't proceed
if (not is_looted) then
return
end
-- Increat field dressings stat
game_statistics.increment_statistic("field_dressings")
-- Mutant post-state
save_var(obj_mutant,"loot",self.loot)
local is_more_loot = not is_empty(self.loot)
-- Refill loot list if there's loot left
if ((not actor_effects.is_animations_on()) and is_more_loot) then
self:FillList()
else
self:Close()
end
end
function UIMutantLoot:FillList()
--developed by Dimeyne, copied by Wafel
self.loot = load_var(self.obj,"loot",nil)
if not self.loot then
self.loot = {}
loot_mutant(self.section, self.clsid, self.loot, nil, true, self.obj)
save_var(self.obj,"loot",self.loot)
end
local is_there_loot
local inv = {}
for sec,t in pairs(self.loot) do
for i=1,t.count do
inv[#inv + 1] = sec
end
is_there_loot = true
end
if (self.obj:clsid() ~= clsid.crow) and load_var(self.obj,"looted",nil) then --Exclude crows from this check since they're managed by bind_crow.script -tB
is_there_loot = false
end
if is_there_loot then
--Flipping the inventory array so unique parts show up first like eyes and feet. I could sort it more specificly, but this is good enough. -tB
local flippedInv = {}
for i=#inv, 1, -1 do
flippedInv[#flippedInv + 1] = inv[i]
end
self:ShowDialog(true)
self.CC:Reinit(flippedInv,nil,true)
return true
else
actor_menu.set_msg(1, "st_body_useless",3)
end
end
function UIMutantLoot:SetMutantState(is_more_loot, obj_mutant)
obj_mutant = obj_mutant or level.object_by_id(self.id)
if (is_more_loot == nil) then
is_more_loot = not is_empty(self.loot)
end
-- We set mutant state to looted or not if there's loot left, so other NPCs can decide what to do with the corpse
if obj_mutant then
if is_more_loot then
se_save_var(obj_mutant:id(),obj_mutant:name(),"looted",false)
xr_corpse_detection.set_valuable_loot(self.id,true)
else
se_save_var(obj_mutant:id(),obj_mutant:name(),"looted",true)
xr_corpse_detection.set_valuable_loot(self.id,false)
end
else
printe("!ERROR ui_mutant_loot | can't retrieve online object of mutant [%s](%s)", self.section, self.id)
end
end
-- Callbacks
function UIMutantLoot:On_CC_Mouse1(cont, idx)
local ci = self.CC.cell[idx]
if (not ci) then
return
end
if (not ci.flags.selected) then
ci.flags.selected = true
else
ci.flags.selected = nil
end
end
function UIMutantLoot:OnButton_LootSelected()
self:Loot(false)
end
function UIMutantLoot:OnButton_LootAll()
self:Loot(true)
end
function UIMutantLoot:Close()
self:SetMutantState()
self:HideDialog()
Unregister_UI("UIMutantLoot")
end
function UIMutantLoot:OnKeyboard(dik, keyboard_action)
local res = CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
if (res == false) then
self.CC:OnKeyboard(dik, keyboard_action)
if (dik == DIK_keys.DIK_RETURN) then
self:OnButton_LootAll()
elseif (dik == DIK_keys.DIK_ESCAPE) then
self:Close()
end
end
return res
end