mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there. * Declared existing Entity APIs. * Added basic script context caching * Started Lua script module * Started Lua spell effect API * Started script state persistence * Started battle info callback binding * CommitPackage removed * Extracted spells::Caster to own header; Expanded Spell API. * implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C * !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented * Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key) * Re-enabled VERM macros. * !?GM0 added * !?TM implemented * Added !!MF:N * Started !?OB, !!BM, !!HE, !!OW, !!UN * Added basic support of w-variables * Added support for ERM indirect variables * Made !?FU regular trigger * !!re (ERA loop receiver) implemented * Fixed ERM receivers with zero args.
This commit is contained in:
233
scripts/lib/erm/MA.lua
Normal file
233
scripts/lib/erm/MA.lua
Normal file
@@ -0,0 +1,233 @@
|
||||
local logError = logError
|
||||
local bit = bit
|
||||
|
||||
local ReceiverBase = require("core:erm.ReceiverBase")
|
||||
local Metatype = require ("core:Metatype")
|
||||
local EntitiesChanged = require("netpacks.EntitiesChanged")
|
||||
local Bonus = require("Bonus")
|
||||
local BonusBearer = require("BonusBearer")
|
||||
local BonusList = require("BonusList")
|
||||
|
||||
local RES = {[0] = "wood", [1] = "mercury", [2] = "ore", [3] = "sulfur", [4] = "crystal", [5] = "gems", [6] = "gold", [7] = "mithril"}
|
||||
|
||||
local SERVICES = SERVICES
|
||||
local creatures = SERVICES:creatures()
|
||||
local SERVER = SERVER
|
||||
|
||||
local getCreatureByIndex = creatures.getByIndex
|
||||
local function creatureByIndex(index)
|
||||
return getCreatureByIndex(creatures, index)
|
||||
end
|
||||
|
||||
local function sendChanges(creatureIndex, data)
|
||||
local pack = EntitiesChanged.new()
|
||||
pack:update(Metatype.CREATURE, creatureIndex, data)
|
||||
SERVER:commitPackage(pack)
|
||||
end
|
||||
|
||||
local MA = ReceiverBase:new()
|
||||
|
||||
function MA:new(ERM)
|
||||
return ReceiverBase.new(self,{ERM = ERM})
|
||||
end
|
||||
|
||||
local function checkCreatureIndex(creatureIndex)
|
||||
assert(creatureIndex ~= nil, "!!MA requires creature identifier")
|
||||
|
||||
if type(creatureIndex) == "string" then
|
||||
error("Identifier resolving is not implemented")
|
||||
end
|
||||
|
||||
return creatureIndex
|
||||
end
|
||||
|
||||
local function createModifier(scope, jsonKey, getterKey)
|
||||
|
||||
local f = function (self, x, creatureIndex, p1)
|
||||
local creatureIndex = checkCreatureIndex(creatureIndex)
|
||||
|
||||
if p1 == nil then
|
||||
local creature = creatureByIndex(creatureIndex)
|
||||
return nil, creature[getterKey](creature)
|
||||
else
|
||||
local packData = {config = {}}
|
||||
|
||||
local config = packData.config
|
||||
|
||||
for _, v in ipairs(scope) do
|
||||
config[v] = {}
|
||||
config = config[v]
|
||||
end
|
||||
|
||||
config[jsonKey] = p1
|
||||
|
||||
sendChanges(creatureIndex, packData)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return f
|
||||
end
|
||||
|
||||
MA.A = createModifier({}, "attack", "getBaseAttack")
|
||||
MA.B = createModifier({}, "spellPoints" ,"getBaseSpellPoints")
|
||||
MA.D = createModifier({}, "defense" ,"getBaseDefense")
|
||||
MA.E = createModifier({"damage"}, "max", "getBaseDamageMax")
|
||||
MA.F = createModifier({}, "fightValue" ,"getFightValue")
|
||||
MA.G = createModifier({}, "growth" ,"getGrowth")
|
||||
MA.H = createModifier({"advMapAmount"}, "max" ,"getAdvMapAmountMax")
|
||||
MA.I = createModifier({}, "aiValue" ,"getAIValue")
|
||||
MA.L = createModifier({}, "level" , "getLevel")
|
||||
MA.M = createModifier({"damage"}, "min", "getBaseDamageMin")
|
||||
MA.N = createModifier({}, "shots" , "getBaseShots")
|
||||
MA.O = createModifier({}, "faction" ,"getFactionIndex")
|
||||
MA.P = createModifier({}, "hitPoints" ,"getBaseHitPoints")
|
||||
MA.R = createModifier({}, "horde" , "getHorde")
|
||||
MA.S = createModifier({}, "speed" , "getBaseSpeed")
|
||||
MA.V = createModifier({"advMapAmount"}, "min","getAdvMapAmountMin")
|
||||
|
||||
function MA:C(x, creatureIndex, resIndex, cost)
|
||||
local creatureIndex = checkCreatureIndex(creatureIndex)
|
||||
|
||||
if cost == nil then
|
||||
local creature = creatureByIndex(creatureIndex)
|
||||
return nil, nil, creature:getCost(resIndex)
|
||||
else
|
||||
local packData = {config = {cost = {[RES[resIndex]] = cost}}}
|
||||
sendChanges(creatureIndex, packData)
|
||||
end
|
||||
end
|
||||
|
||||
function MA:U(x, creatureIndex, upgradeIndex)
|
||||
-- -2 - no upgrade
|
||||
-- -1 - usual upgrade
|
||||
logError("!!MA:U is not implemented")
|
||||
end
|
||||
|
||||
local FLAG_NAMES =
|
||||
{
|
||||
--[1] = "doubleWide", --0
|
||||
[2] = "FLYING", --1
|
||||
[4] = "SHOOTER", --2
|
||||
[8] = "TWO_HEX_ATTACK_BREATH", --3
|
||||
-- [16] = "alive", --4
|
||||
[32] = "CATAPULT", --5
|
||||
[64] = "SIEGE_WEAPON", --6
|
||||
[128] = "KING1", --7
|
||||
[256] = "KING2", --8
|
||||
[512] = "KING3", --9
|
||||
[1024] = "MIND_IMMUNITY", --10
|
||||
--[2048] = "laser shot", --11
|
||||
[4096] = "NO_MELEE_PENALTY", --12
|
||||
-- [8192] - unused --13
|
||||
[16384] = "FIRE_IMMUNITY", --14
|
||||
[32768] = "ADDITIONAL_ATTACK", -- val=1 --15
|
||||
[65536] = "NO_RETALIATION", --16
|
||||
[131072] = "NO_MORALE", --17
|
||||
[262144] = "UNDEAD", --18
|
||||
[524288] = "ATTACKS_ALL_ADJACENT", --19
|
||||
-- [1048576] - AOE spell-like attack --20
|
||||
-- [2097152] - war machine? --21
|
||||
-- [4194304] = "summoned", --22
|
||||
-- [8388608] = "cloned", --23
|
||||
}
|
||||
|
||||
local FLAGS = {}
|
||||
|
||||
for k, v in pairs(FLAG_NAMES) do
|
||||
local bonusType = Bonus[v]
|
||||
assert(bonusType ~= nil, "Invalid Bonus type: "..v)
|
||||
FLAGS[k] = bonusType
|
||||
end
|
||||
|
||||
local FLAGS_REV = {}
|
||||
|
||||
for mask, bonusType in pairs(FLAGS) do
|
||||
FLAGS_REV[bonusType] = mask
|
||||
end
|
||||
|
||||
function MA:X(x, creatureIndex, flagsMask)
|
||||
local creatureIndex = checkCreatureIndex(creatureIndex)
|
||||
local creature = creatureByIndex(creatureIndex)
|
||||
local creatureBonuses = creature:accessBonuses()
|
||||
local all = creatureBonuses:getBonuses()
|
||||
|
||||
local currentMask = 0
|
||||
|
||||
local toRemove = {}
|
||||
|
||||
do
|
||||
local idx = 1
|
||||
local bonus = all[idx]
|
||||
|
||||
while bonus do
|
||||
local bonusType = bonus:getType()
|
||||
local mask = FLAGS_REV[bonusType]
|
||||
|
||||
if mask ~= nil then
|
||||
if flagsMask ~= nil then
|
||||
if bit.band(mask, flagsMask) == 0 then
|
||||
table.insert(toRemove, bonus:toJsonNode())
|
||||
end
|
||||
end
|
||||
currentMask = bit.bor(currentMask, mask)
|
||||
end
|
||||
|
||||
|
||||
idx = idx + 1
|
||||
bonus = all[idx]
|
||||
end
|
||||
end
|
||||
|
||||
if flagsMask == nil then
|
||||
local ret = currentMask
|
||||
|
||||
if creature:isDoubleWide() then
|
||||
ret = bit.bor(ret, 1)
|
||||
end
|
||||
|
||||
return nil, ret
|
||||
else
|
||||
flagsMask = tonumber(flagsMask)
|
||||
|
||||
local hasChanges = false
|
||||
local packData = {config = {}}
|
||||
|
||||
local reqDoubleWide = bit.band(flagsMask, 1) > 0
|
||||
|
||||
if reqDoubleWide ~= creature:isDoubleWide() then
|
||||
packData.config.doubleWide, hasChanges = reqDoubleWide, true
|
||||
end
|
||||
|
||||
local toAdd = {}
|
||||
|
||||
for mask, name in pairs(FLAG_NAMES) do
|
||||
if (bit.band(currentMask, mask) == 0) and (bit.band(flagsMask, mask) ~= 0) then
|
||||
local bonus =
|
||||
{
|
||||
duration = {[1] = "PERMANENT"},
|
||||
source = "CREATURE_ABILITY",
|
||||
type = name
|
||||
}
|
||||
|
||||
--special case
|
||||
if name == "ADDITIONAL_ATTACK" then
|
||||
bonus.val = 1
|
||||
end
|
||||
|
||||
table.insert(toAdd, bonus)
|
||||
end
|
||||
end
|
||||
|
||||
hasChanges = hasChanges or #toAdd > 0 or #toRemove > 0
|
||||
|
||||
if hasChanges then
|
||||
packData.bonuses = {toAdd = toAdd, toRemove = toRemove}
|
||||
sendChanges(creatureIndex, packData)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return MA
|
||||
Reference in New Issue
Block a user