123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- 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"}
- 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" ,"getFaction")
- 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:getBonusBearer()
- 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
|