ToME: the Tales of Maj'Eyal

Everything about ToME
It is currently Wed May 27, 2020 9:29 pm

All times are UTC

Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Mon Jul 28, 2014 1:22 pm 

Joined: Tue May 14, 2013 3:45 pm
Posts: 884
I have a spell that applies a damage shield to the player, Crimson Barrier. While the shield holds, they gain a number of bonuses. This was working fine, until a player noticed that if they used a shielding rune with a shorter duration while the spell was active, once the rune expired the game would lock up. This appears to be because damage shields have the 'self.damage_shield_absorb = nil' line when they expire, so despite there being another damage shield active, the value would be set to nil causing the UIset to freak out.
So I'm looking for advice on what would be the best way to fix it. Creating a brand new type of damage shield along the lines of Time Shield, which sounds like it'd be very difficult via addon? I'm leaning towards just preventing the use of other shielding while Crimson Barrier is active and visa versa, but I'm unsure how to best implement that. I've included the code for the timed effect below.

   name = "CRIMSON_BARRIER", image = "talents/crimson_barrier.png",
   desc = "Crimson Barrier",
   long_desc = function(self, eff) return ("The target is surrounded by a shield of blood, absorbing %d/%d damage, increasing healing factor by %d%% and draining %0.2f life from attackers."):format(self.damage_shield_absorb, eff.power, eff.heal, eff.dam) end,
   type = "magical",
   subtype = { arcane=true, shield=true },
   status = "beneficial",
   parameters = { power=100, healing=1, dam=1, empower=0 },
   on_gain = function(self, err) return "A bloody shield forms around #target#.", "+Shield" end,
   on_lose = function(self, err) return "The bloody shield around #target# crumbles.", "-Shield" end,
   on_aegis = function(self, eff, aegis)
      self.damage_shield_absorb = self.damage_shield_absorb + eff.power * aegis / 100
      if then
         local bc = {0.4, 0.7, 1.0, 1.0}
         local ac = {0x21/255, 0x9f/255, 0xff/255, 1}
         if eff.color then
            bc = table.clone(eff.color) bc[4] = 1
            ac = table.clone(eff.color) ac[4] = 1
         eff.particle = self:addParticles("shader_shield", 1, {size_factor=1.3, img="runicshield"}, {type="runicshield", shieldIntensity=0.14, ellipsoidalFactor=1.2, time_factor=5000, bubbleColor=bc, auraColor=ac}))
   damage_feedback = function(self, eff, src, value)
      if eff.particle and eff.particle._shader and eff.particle._shader.shad and src and src.x and src.y then
         local r = -rng.float(0.2, 0.4)
         local a = math.atan2(src.y - self.y, src.x - self.x)
         eff.particle._shader:setUniform("impact", {math.cos(a) * r, math.sin(a) * r})
   activate = function(self, eff)
      if self:attr("shield_factor") then eff.power = eff.power * (100 + self:attr("shield_factor")) / 100 end
      if self:attr("shield_dur") then eff.dur = eff.dur + self:attr("shield_dur") end
      eff.tmpid = self:addTemporaryValue("damage_shield", eff.power)
      self.damage_shield_absorb = eff.power
      self.damage_shield_absorb_max = eff.power
      eff.healid = self:addTemporaryValue("healing_factor", eff.heal/100)
      eff.leechid = self:addTemporaryValue("on_melee_hit", {[DamageType.DEVOUR_LIFE]=eff.dam})
      if then
         eff.particle = self:addParticles("shader_shield", 1, nil, {type="shield", shieldIntensity=0.2, color=eff.color or {0.4, 0.7, 1.0}}))
         eff.particle = self:addParticles("damage_shield", 1))
   deactivate = function(self, eff)
      self:removeTemporaryValue("damage_shield", eff.tmpid)
      self.damage_shield_absorb = nil
      self.damage_shield_absorb_max = nil
      self:removeTemporaryValue("healing_factor", eff.healid)
      self:removeTemporaryValue("on_melee_hit", eff.leechid)       
   on_timeout = function(self, eff)
      if eff.empower == 1 then
         self:project({type="ball", range=0, friendlyfire=false, radius=3}, self.x, self.y, function(px, py)
            local target =, py, Map.ACTOR)
            if not target then return end
                  if self:reactionToward(target) < 0 then
                     DamageType:get(DamageType.DEVOUR_LIFE).projector(self, target.x, target.y, DamageType.DEVOUR_LIFE, eff.dam*2)

PostPosted: Mon Jul 28, 2014 1:39 pm 

Joined: Wed Apr 30, 2008 5:55 pm
Posts: 708
I stuck my not-a-damage-shield in the Actor:takeHit hook instead of using the existing damage shield system. You could do something like that.

Simplified version of mine for reference:
-- Actor:takeHit
hook = function(self, data)
   local value = data.value
   local src = data.src
   local damtype = table.get(data, 'death_note', 'damtype')

   -- Jagged Body
   if value > 0 and self:knowTalent('T_JAGGED_BODY') then
      local blocked = math.min(self.jaggedbody, value)
      self.jaggedbody = self.jaggedbody - blocked
      value = value - blocked
         src, self, 0, ('#SLATE#(%d absorbed)#LAST#'):format(blocked), false)

   data.value = value
   return true
class:bindHook('Actor:takeHit', hook)

Addons: Arcane Blade Tweaks, Fallen Race, Monk Class, Weapons Pack
Currently working on Elementals. It's a big project, so any help would be appreciated. :)

PostPosted: Wed Jul 30, 2014 12:02 pm 

Joined: Tue May 14, 2013 3:45 pm
Posts: 884
Got it working, thanks.

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC

Who is online

Users browsing this forum: No registered users and 2 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group