147 lines
5.6 KiB
Lua
147 lines
5.6 KiB
Lua
-- Consent Required API
|
|
-- Any Lua script can access this API by adding this line:
|
|
-- local Api = require "com.github.cintique.ConsentRequired.Api"
|
|
local Environment = require("ConsentRequiredExtended.Util.Environment")
|
|
local Barotrauma = require("ConsentRequiredExtended.Util.Barotrauma")
|
|
|
|
local _ENV = Environment.PrepareEnvironment(_ENV)
|
|
|
|
-- Table of identifiers (strings) of items that when used
|
|
-- as a treatment on an NPC from a different team,
|
|
-- causes that NPC (and their allies) to become hostile
|
|
-- towards the player.
|
|
local affectedItems = {}
|
|
|
|
---Adds an item (by identifier string) to `affectedItems`.
|
|
---@param identifier string
|
|
function AddAffectedItem(identifier)
|
|
table.insert(affectedItems, identifier)
|
|
end
|
|
|
|
LuaUserData.MakeFieldAccessible(Descriptors["Barotrauma.AbandonedOutpostMission"], "requireRescue")
|
|
|
|
-- Character type doesn't have tags we can assign a custom "rescuetarget" tag to
|
|
-- So instead we just hold characters which need rescue in a table and compare their entity IDs
|
|
-- This table is only resfreshed on roundstart
|
|
local rescuetargets = {}
|
|
|
|
---Returns a boolean indicating whether a given item is affected or not.
|
|
---@param identifier string The identifier of the item that we are testing.
|
|
---@return boolean isAffected True if the item is affected, false otherwise.
|
|
function IsItemAffected(identifier)
|
|
for _, item in pairs(affectedItems) do
|
|
if item == identifier or HF.StartsWith(identifier, item) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local ADD_ATTACKER_DAMAGE = 130 -- Heelge: this used to max out negative rep gain, now only around 4 negative rep, any less negative rep is too forgiving.
|
|
|
|
---@param aiChar Barotrauma_Character The AI character to be made hostile.
|
|
---@param instigator Barotrauma_Character The character to be the target of the AI's wrath.
|
|
function makeHostile(aiChar, instigator)
|
|
aiChar.AIController.OnAttacked(instigator, Barotrauma.AttackResult.NewAttackResultFromDamage(ADD_ATTACKER_DAMAGE))
|
|
aiChar.AddAttacker(instigator, ADD_ATTACKER_DAMAGE)
|
|
end
|
|
|
|
---@param char1 Barotrauma_Character Character one.
|
|
---@param char2 Barotrauma_Character Character two.
|
|
---@return boolean charactersAreOnSameTeam True if characters one & two are on the same team, false otherwise.
|
|
function isOnSameTeam(char1, char2)
|
|
local team1 = char1.TeamID
|
|
local team2 = char2.TeamID
|
|
return team1 == team2
|
|
end
|
|
|
|
---Updates current rescue targets list, separate so we dont cycle thru all missions every time we apply item to chacter. Use IsRescueTarget(target) after this.
|
|
function UpdateRescueTargets()
|
|
rescuetargets = {}
|
|
for mission in Game.GameSession.Missions do
|
|
if LuaUserData.IsTargetType(mission.Prefab.MissionClass, "Barotrauma.AbandonedOutpostMission") then
|
|
for character in mission.requireRescue do
|
|
rescuetargets[character.ID] = character
|
|
--table.insert(rescuetargets, character)
|
|
end
|
|
end
|
|
end
|
|
-- print('rescue targets =')
|
|
-- for char in rescuetargets do print(char.Name) end
|
|
end
|
|
|
|
---@param target Barotrauma_Character The character we want to confirm as being rescued
|
|
---@return boolean consent True if target is rescue mission target, false otherwise
|
|
function IsRescueTarget(target)
|
|
-- for char in rescuetargets do
|
|
-- if target.ID == char.ID then return true end
|
|
-- end
|
|
if rescuetargets[target.ID] ~= nil then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
---@param user Barotrauma_Character The character who desires consent.
|
|
---@param target Barotrauma_Character The character who gives consent
|
|
---@return boolean consent True if consent is given, false otherwise.
|
|
function hasConsent(user, target)
|
|
return isOnSameTeam(user, target) or target.IsEscorted or IsRescueTarget(target) -- No longer needs to be shared.
|
|
end
|
|
|
|
---@param aiChar Barotrauma_Character The (AI but not necessarily) character whose sight is being tested.
|
|
---@param target Barotrauma_Character The character to be seen.
|
|
---@return boolean aiCanSeeTarget True if the AI can see the target character.
|
|
function canAiSeeTarget(aiChar, target)
|
|
-- I'll just use what Barotrauma uses for witness line of sight
|
|
local aiVisibleHulls = aiChar.GetVisibleHulls()
|
|
local targetCurrentHull = target.CurrentHull
|
|
for _, visibleHull in pairs(aiVisibleHulls) do
|
|
if targetCurrentHull == visibleHull then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
---@param user Barotrauma_Character The character of the instigator being witnessed.
|
|
---@param victim Barotrauma_Character The character of the victim of the crime being witnessed.
|
|
---@return Barotrauma_Character[] Characters that have witnessed the crime.
|
|
function getWitnessesToCrime(user, victim)
|
|
local witnesses = {}
|
|
for _, char in pairs(Character.CharacterList) do
|
|
if
|
|
not char.Removed
|
|
and not char.IsUnconscious
|
|
and char.IsBot
|
|
and char.IsHuman
|
|
and isOnSameTeam(char, victim)
|
|
then
|
|
local isWitnessingUser = canAiSeeTarget(char, user)
|
|
if isWitnessingUser then
|
|
table.insert(witnesses, char)
|
|
end
|
|
end
|
|
end
|
|
return witnesses
|
|
end
|
|
|
|
---@param user Barotrauma_Character The character that is applying the affected item.
|
|
---@param target Barotrauma_Character The character of the target of the affected item's application.
|
|
function onAffectedItemApplied(user, target)
|
|
if not hasConsent(user, target) and target.IsBot and target.IsHuman then
|
|
if not target.IsIncapacitated and target.Stun <= 10 then
|
|
makeHostile(target, user)
|
|
else
|
|
-- Vanilla Barotrauma Human AI doesn't care what you do to their unconscious teammates, even shooting them in the head
|
|
-- Let's fix that for this particular case of mistreatment
|
|
local witnesses = getWitnessesToCrime(user, target)
|
|
for _, witness in pairs(witnesses) do
|
|
makeHostile(witness, user)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return Environment.Export(_ENV)
|