MA.lua 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. local logError = logError
  2. local bit = bit
  3. local ReceiverBase = require("core:erm.ReceiverBase")
  4. local Metatype = require ("core:Metatype")
  5. local EntitiesChanged = require("netpacks.EntitiesChanged")
  6. local Bonus = require("Bonus")
  7. local BonusBearer = require("BonusBearer")
  8. local BonusList = require("BonusList")
  9. local RES = {[0] = "wood", [1] = "mercury", [2] = "ore", [3] = "sulfur", [4] = "crystal", [5] = "gems", [6] = "gold"}
  10. local SERVICES = SERVICES
  11. local creatures = SERVICES:creatures()
  12. local SERVER = SERVER
  13. local getCreatureByIndex = creatures.getByIndex
  14. local function creatureByIndex(index)
  15. return getCreatureByIndex(creatures, index)
  16. end
  17. local function sendChanges(creatureIndex, data)
  18. local pack = EntitiesChanged.new()
  19. pack:update(Metatype.CREATURE, creatureIndex, data)
  20. SERVER:commitPackage(pack)
  21. end
  22. local MA = ReceiverBase:new()
  23. function MA:new(ERM)
  24. return ReceiverBase.new(self,{ERM = ERM})
  25. end
  26. local function checkCreatureIndex(creatureIndex)
  27. assert(creatureIndex ~= nil, "!!MA requires creature identifier")
  28. if type(creatureIndex) == "string" then
  29. error("Identifier resolving is not implemented")
  30. end
  31. return creatureIndex
  32. end
  33. local function createModifier(scope, jsonKey, getterKey)
  34. local f = function (self, x, creatureIndex, p1)
  35. local creatureIndex = checkCreatureIndex(creatureIndex)
  36. if p1 == nil then
  37. local creature = creatureByIndex(creatureIndex)
  38. return nil, creature[getterKey](creature)
  39. else
  40. local packData = {config = {}}
  41. local config = packData.config
  42. for _, v in ipairs(scope) do
  43. config[v] = {}
  44. config = config[v]
  45. end
  46. config[jsonKey] = p1
  47. sendChanges(creatureIndex, packData)
  48. return
  49. end
  50. end
  51. return f
  52. end
  53. MA.A = createModifier({}, "attack", "getBaseAttack")
  54. MA.B = createModifier({}, "spellPoints" ,"getBaseSpellPoints")
  55. MA.D = createModifier({}, "defense" ,"getBaseDefense")
  56. MA.E = createModifier({"damage"}, "max", "getBaseDamageMax")
  57. MA.F = createModifier({}, "fightValue" ,"getFightValue")
  58. MA.G = createModifier({}, "growth" ,"getGrowth")
  59. MA.H = createModifier({"advMapAmount"}, "max" ,"getAdvMapAmountMax")
  60. MA.I = createModifier({}, "aiValue" ,"getAIValue")
  61. MA.L = createModifier({}, "level" , "getLevel")
  62. MA.M = createModifier({"damage"}, "min", "getBaseDamageMin")
  63. MA.N = createModifier({}, "shots" , "getBaseShots")
  64. MA.O = createModifier({}, "faction" ,"getFaction")
  65. MA.P = createModifier({}, "hitPoints" ,"getBaseHitPoints")
  66. MA.R = createModifier({}, "horde" , "getHorde")
  67. MA.S = createModifier({}, "speed" , "getBaseSpeed")
  68. MA.V = createModifier({"advMapAmount"}, "min","getAdvMapAmountMin")
  69. function MA:C(x, creatureIndex, resIndex, cost)
  70. local creatureIndex = checkCreatureIndex(creatureIndex)
  71. if cost == nil then
  72. local creature = creatureByIndex(creatureIndex)
  73. return nil, nil, creature:getCost(resIndex)
  74. else
  75. local packData = {config = {cost = {[RES[resIndex]] = cost}}}
  76. sendChanges(creatureIndex, packData)
  77. end
  78. end
  79. function MA:U(x, creatureIndex, upgradeIndex)
  80. -- -2 - no upgrade
  81. -- -1 - usual upgrade
  82. logError("!!MA:U is not implemented")
  83. end
  84. local FLAG_NAMES =
  85. {
  86. --[1] = "doubleWide", --0
  87. [2] = "FLYING", --1
  88. [4] = "SHOOTER", --2
  89. [8] = "TWO_HEX_ATTACK_BREATH", --3
  90. -- [16] = "alive", --4
  91. [32] = "CATAPULT", --5
  92. [64] = "SIEGE_WEAPON", --6
  93. [128] = "KING1", --7
  94. [256] = "KING2", --8
  95. [512] = "KING3", --9
  96. [1024] = "MIND_IMMUNITY", --10
  97. --[2048] = "laser shot", --11
  98. [4096] = "NO_MELEE_PENALTY", --12
  99. -- [8192] - unused --13
  100. [16384] = "FIRE_IMMUNITY", --14
  101. [32768] = "ADDITIONAL_ATTACK", -- val=1 --15
  102. [65536] = "NO_RETALIATION", --16
  103. [131072] = "NO_MORALE", --17
  104. [262144] = "UNDEAD", --18
  105. [524288] = "ATTACKS_ALL_ADJACENT", --19
  106. -- [1048576] - AOE spell-like attack --20
  107. -- [2097152] - war machine? --21
  108. -- [4194304] = "summoned", --22
  109. -- [8388608] = "cloned", --23
  110. }
  111. local FLAGS = {}
  112. for k, v in pairs(FLAG_NAMES) do
  113. local bonusType = Bonus[v]
  114. assert(bonusType ~= nil, "Invalid Bonus type: "..v)
  115. FLAGS[k] = bonusType
  116. end
  117. local FLAGS_REV = {}
  118. for mask, bonusType in pairs(FLAGS) do
  119. FLAGS_REV[bonusType] = mask
  120. end
  121. function MA:X(x, creatureIndex, flagsMask)
  122. local creatureIndex = checkCreatureIndex(creatureIndex)
  123. local creature = creatureByIndex(creatureIndex)
  124. local creatureBonuses = creature:getBonusBearer()
  125. local all = creatureBonuses:getBonuses()
  126. local currentMask = 0
  127. local toRemove = {}
  128. do
  129. local idx = 1
  130. local bonus = all[idx]
  131. while bonus do
  132. local bonusType = bonus:getType()
  133. local mask = FLAGS_REV[bonusType]
  134. if mask ~= nil then
  135. if flagsMask ~= nil then
  136. if bit.band(mask, flagsMask) == 0 then
  137. table.insert(toRemove, bonus:toJsonNode())
  138. end
  139. end
  140. currentMask = bit.bor(currentMask, mask)
  141. end
  142. idx = idx + 1
  143. bonus = all[idx]
  144. end
  145. end
  146. if flagsMask == nil then
  147. local ret = currentMask
  148. if creature:isDoubleWide() then
  149. ret = bit.bor(ret, 1)
  150. end
  151. return nil, ret
  152. else
  153. flagsMask = tonumber(flagsMask)
  154. local hasChanges = false
  155. local packData = {config = {}}
  156. local reqDoubleWide = bit.band(flagsMask, 1) > 0
  157. if reqDoubleWide ~= creature:isDoubleWide() then
  158. packData.config.doubleWide, hasChanges = reqDoubleWide, true
  159. end
  160. local toAdd = {}
  161. for mask, name in pairs(FLAG_NAMES) do
  162. if (bit.band(currentMask, mask) == 0) and (bit.band(flagsMask, mask) ~= 0) then
  163. local bonus =
  164. {
  165. duration = {[1] = "PERMANENT"},
  166. source = "CREATURE_ABILITY",
  167. type = name
  168. }
  169. --special case
  170. if name == "ADDITIONAL_ATTACK" then
  171. bonus.val = 1
  172. end
  173. table.insert(toAdd, bonus)
  174. end
  175. end
  176. hasChanges = hasChanges or #toAdd > 0 or #toRemove > 0
  177. if hasChanges then
  178. packData.bonuses = {toAdd = toAdd, toRemove = toRemove}
  179. sendChanges(creatureIndex, packData)
  180. end
  181. end
  182. end
  183. return MA