Page 216 of 400

Re: Ask a simple question, get a simple answer

Posted: Tue Jan 09, 2018 7:28 pm
by Isaac
Here is an alternate holy_water_flask. It is not a tile-damager, and affects single monsters, one at a time; even in groups. It is possible to miss with these. It could certainly use a custom model and icon; it presently uses default assets.

Code: Select all

defineObject{
	name = "holy_water_flask",
	baseObject = "flask",
	components = {
		{
			class = "Item",
			uiName = "Holy Water Flask",
			gameEffect = "Burns the undead",
			description = "A flask of blessed water.",
			gfxIndex = 150,
			impactSound = "impact_blunt",
			stackable = true,
			projectileRotationSpeed = 15,
			projectileRotationZ = -50,
			projectileRotationY = 40,
			weight = 0.5,
			stackable = true,
			traits = { "throwing_weapon" },
			ConvertToItemOnImpact = "holy_water_spray",
			onThrowAttackHitMonster = function(self, monster)
										monster.go:playSound("water_hit_small")
										if  monster.go.monster:hasTrait('undead') and not monster.go.burningmonster then
											monster.go:createComponent('BurningMonster')
											monster.go.poisonedParticle:setParticleSystem("devine_flames")
											monster.go:playSound("ice_hit")
											monster.go.burningmonster:setCausedByChampion(math.random(4))
											--[[ So I had an elaborate system in place to detect which champion
												 tossed the holy water flask; for the XP award after the monster dies.

												 But then I discover that the game apparently doesn't care (!?); it splits
												 the XP between the party members regardless of who caused the damage.
												So what is the purpose of :setCausedByChampion? (Because it's not Boolean)
											--]]
										end
									end	
		},
		{
			class = "ThrowAttack",
			attackPower = 2,
			cooldown = 4,
		},
	},
	tags = { "weapon", "weapon_throwing" },
}

defineObject{
	name = "holy_water_spray",
	baseObject = "base_spell",
	components = {
		{
			class = "Particle",
			particleSystem = "hit_ice",
			offset = vec(0, 1.5, 0),
		},	
	},
}

defineParticleSystem{
	name = "devine_flames",
	emitters = {
		{
			emitterShape = "MeshShape",
			emissionRate = 50,
			emissionTime = 0,
			maxParticles = 50,
			sprayAngle = {0,360},
			velocity = {0.1*2,0.5*2},
			texture = "assets/textures/particles/smoke_01.tga",
			lifetime = {0.5,0.7},
			color = {0.15, 0.15, 0.15},
			opacity = 1,
			fadeIn = 0.1,
			fadeOut = 0.5,
			size = {0.5, 1.3},
			gravity = {0,2,0},
			airResistance = 0.05,
			rotationSpeed = 0.6,
			blendMode = "Translucent",
			depthBias = 0.1,
		},
		{
			-- flames
			emitterShape = "MeshShape",
			maxParticles = 400,
			emissionRate = 600,
			emissionTime = 0,
			sprayAngle = {0,30},
			velocity = {0.0, 0.0},
			texture = "assets/textures/particles/flame.tga",
			frameRate = 40,
			frameSize = 32,
			frameCount = 40,
			lifetime = {0.4, 0.7},
			colorAnimation = true,
			color0 = {.2, .2, 2.0},
			color1 = {0.2, 0.2, 2.0},
			color2 = {0.3, 0.5, 1.25},
			color3 = {0.1, 0.1, 2},
			fadeIn = 0.01,
			fadeOut = 0.1,
			size = {0.021*2, 0.12*3},
			gravity = {0,3,0},
			airResistance = 1,
			rotationSpeed = 0,
			blendMode = "Additive",
			objectSpace = true,
		},
		{
			-- small flames
			emitterShape = "MeshShape",
			maxParticles = 400,
			emissionRate = 500,
			emissionTime = 0,
			sprayAngle = {0,30},
			velocity = {0.0, 0.0},
			texture = "assets/textures/particles/flame.tga",
			frameRate = 40,
			frameSize = 32,
			frameCount = 40,
			lifetime = {0.2, 0.4},
			colorAnimation = true,
			color0 = {.2, .2, 2.0},
			color1 = {0.2, 0.2, 2.0},
			color2 = {0.3, 0.5, 1.25},
			color3 = {0.1, 0.1, 2},
			fadeIn = 0.01,
			fadeOut = 0.1,
			size = {0.021*2*0.5, 0.12*3*0.7},
			gravity = {0,4,0},
			airResistance = 1,
			rotationSpeed = 0,
			blendMode = "Additive",
		},
	}
}

Re: Ask a simple question, get a simple answer

Posted: Wed Jan 10, 2018 11:39 pm
by zimberzimber
bongobeat wrote:Hey there,
I'm not sure that I understand this corectly

You mean that if I throw one bomb (with the code of Akroma) on a monster groupe, it will spawn a fireburst for every monster that is part of the monstergroup?
Is that not the same thing when you throw a fire bomb or any other bomb on a monster group?
Normal bombs just spawn a tile damager where they land.
Akromas code spawns a tile damage for every monster on the tile.

But you don't have to use my method, you can just have onExplode spawn the tile damaging object on its location as it happens when the bomb would explode. (I forgot you can do that)
But don't forget setting the bomb type to nil so you don't spawn an extra effect on top of that.
It will print an error message to console every time though, but you can disable console error prints when you export the dungeon.
Isaac wrote:So I had an elaborate system in place to detect which champion
tossed the holy water flask; for the XP award after the monster dies.
But then I discover that the game apparently doesn't care (!?); it splits
the XP between the party members regardless of who caused the damage.
So what is the purpose of :setCausedByChampion? (Because it's not Boolean)
IIRC its a remnant from LoG1 where it did matter who delivers the killing blow.

Re: Ask a simple question, get a simple answer

Posted: Thu Jan 11, 2018 2:21 pm
by akroma222
zimberzimber wrote:Akromas code spawns a tile damage for every monster on the tile.
Bad Akroma! :cry:

Place a script entity in your dungeon called 'combatTempScript' with (Zimber's) damageMonster code:
SpoilerShow

Code: Select all

function damageMonster(monster, baseDamage, playerSource, type)
   if not monster:isAlive() then return end
   
   local h = monster:getHealth()
   local mh = monster:getMaxHealth()
   local resist = monster:getResistance(type)
   local damage = baseDamage
   local color = "ffffff"
   
   -- Check for resistances and apply the right damage value/text color.
   if resist == "absorb" then
      healMonster(monster, baseDamage, false)
      return
   elseif resist == "immune" then
      damage = 0
   elseif resist == "resist" then
      damage = baseDamage * 0.5
   elseif resist == "weak" then
      damage = baseDamage * 1.5
      damageColor = "ff0000"
   elseif resist == "vulnerable" then
      damage = baseDamage * 2
      damageColor = "ff0000"
   end
   
   -- Take protection into account if damage is physical
   -- Not really sure if this comes before or after resistance...
   if type == "physical" then
      local protection = monster:getProtection()
      damage = math.max(1, damage - math.floor((math.random() + 0.5) * protection ))
   end
   
   -- Turn the number whole
   damage = roundNumber(damage)
   
   -- No reason to continue the function if damage is 0 or negative
   if damage <= 0 then monster:showDamageText("0", color) return end
   
   -- Apply the damage/heal, print damage text, kill monster if its health will drop below 0, and grant xp if monster died and playerSource was true
  
   if h - damage > 0 then
      monster:showDamageText(""..damage, color)
      monster:setHealth(h - damage)
      monster.go:playSound(monster:getHitSound())
   else
      if playerSource then
        monster:showDamageText("+"..monster:getExp().." xp", "ffeb3f")
         
         for i = 1,4 do
            local champion = party.party:getChampion(i)
            if champion and champion:isAlive() then
              champion:gainExp(monster:getExp())
               
			end 
		end
	 end
      monster:showDamageText(""..h, color)
      monster:die()
   end
end










--------------------------------roundNumber(number)
--Returns a rounded version of the recieved number (1.3 -> 1 | 2.6 -> 3)

function roundNumber(number)
	local rounded = number
	local max = math.ceil(number)
	local min = math.floor(number)
	if math.abs(number - max) < math.abs(number - min) then
		rounded = math.ceil(number)
	else
		rounded = math.floor(number)
	end
	return rounded
end
And try this definition for the HolyWater - its a combined job (Isaac, Zimber, Bongo, Akroma)
SpoilerShow

Code: Select all

defineObject{
   name = "akr_combined_holywater",
   baseObject = "fire_bomb",
   components = {
      {
         class = "Item",
         uiName = "Holy Water",
         gfxIndex = 136,
         impactSound = "impact_blunt",
         stackable = true,
         projectileRotationSpeed = 10,
         projectileRotationZ = -30,
         weight = 1,
         traits = { "throwing_weapon", "bomb" },
      },
      {
         class = "ThrowAttack",
         gameEffect = "............",
         cooldown = 4,
      },
      {
         class = "BombItem",
         onExplode = function(self, level, x, y, facing, elevation)
            
            --print(self:getName(), level, x, y, facing, elevation)
           local undeadMon = false
			
            for entity in Dungeon.getMap(level):entitiesAt(x, y) do       
               
				if entity and entity.monster then
                  
					local entMon = entity.monster
				  
					if entMon:hasTrait("undead") then
                  
						if not undeadMon then
							entMon.go:playSound("water_hit_small")
							undeadMon = true
						end
						print(entity.name)
						 
						entMon.go:createComponent('BurningMonster')
						entMon.go.poisonedParticle:setParticleSystem("devine_flames")
						entMon.go:playSound("frostbolt_hit")
						entMon.go.burningmonster:setCausedByChampion(math.random(4))
						entMon:showDamageText("Burn!", "FF0000")
						 
						local partSys = spawn("particle_system", level, x, y, facing, elevation)
						partSys.particle:setParticleSystem("fireburst")
						partSys.particle:setOffset(vec(0,0,0))
					  
						local power = 35 * self.go.item:getStackSize()
						combatTempScript.script.damageMonster(entMon, rollDamage(power), true, "pure")
					end
               end
            end
				
        end,
         
      },
      
   },
}



defineObject{
   name = "holy_water_spray",
   baseObject = "base_spell",
   components = {
      {
         class = "Particle",
         particleSystem = "hit_ice",
         offset = vec(0, 1.5, 0),
      },   
   },
}

defineParticleSystem{
   name = "devine_flames",
   emitters = {
      {
         emitterShape = "MeshShape",
         emissionRate = 50,
         emissionTime = 0,
         maxParticles = 50,
         sprayAngle = {0,360},
         velocity = {0.1*2,0.5*2},
         texture = "assets/textures/particles/smoke_01.tga",
         lifetime = {0.5,0.7},
         color = {0.15, 0.15, 0.15},
         opacity = 1,
         fadeIn = 0.1,
         fadeOut = 0.5,
         size = {0.5, 1.3},
         gravity = {0,2,0},
         airResistance = 0.05,
         rotationSpeed = 0.6,
         blendMode = "Translucent",
         depthBias = 0.1,
      },
      {
         -- flames
         emitterShape = "MeshShape",
         maxParticles = 400,
         emissionRate = 600,
         emissionTime = 0,
         sprayAngle = {0,30},
         velocity = {0.0, 0.0},
         texture = "assets/textures/particles/flame.tga",
         frameRate = 40,
         frameSize = 32,
         frameCount = 40,
         lifetime = {0.4, 0.7},
         colorAnimation = true,
         color0 = {.2, .2, 2.0},
         color1 = {0.2, 0.2, 2.0},
         color2 = {0.3, 0.5, 1.25},
         color3 = {0.1, 0.1, 2},
         fadeIn = 0.01,
         fadeOut = 0.1,
         size = {0.021*2, 0.12*3},
         gravity = {0,3,0},
         airResistance = 1,
         rotationSpeed = 0,
         blendMode = "Additive",
         objectSpace = true,
      },
      {
         -- small flames
         emitterShape = "MeshShape",
         maxParticles = 400,
         emissionRate = 500,
         emissionTime = 0,
         sprayAngle = {0,30},
         velocity = {0.0, 0.0},
         texture = "assets/textures/particles/flame.tga",
         frameRate = 40,
         frameSize = 32,
         frameCount = 40,
         lifetime = {0.2, 0.4},
         colorAnimation = true,
         color0 = {.2, .2, 2.0},
         color1 = {0.2, 0.2, 2.0},
         color2 = {0.3, 0.5, 1.25},
         color3 = {0.1, 0.1, 2},
         fadeIn = 0.01,
         fadeOut = 0.1,
         size = {0.021*2*0.5, 0.12*3*0.7},
         gravity = {0,4,0},
         airResistance = 1,
         rotationSpeed = 0,
         blendMode = "Additive",
      },
   }
}

Re: Ask a simple question, get a simple answer

Posted: Thu Jan 11, 2018 11:04 pm
by bongobeat
I just had a look this afternoon at both Isaac and Akroma's new versions. Thanks for that! Sorry, I didn't notice that you posted messages here! I thought that this was resolved!

About the fireburst, well ok, I understand now.

Well I'd rather prefer to divise the damage by 2 in my actual definition to limit this "bug" effect, instead of adding a new kind of script, if my version didn't make any crash or error, that's ok for me. This "bomb" is not really "useful". I mean I've only made it to illustrate a part of the story in my mod.

Re: Ask a simple question, get a simple answer

Posted: Wed Jan 17, 2018 6:56 pm
by bongobeat
I got a very simple question :

can I add minimalSaveState = true, to any object that has a ladder component?

Re: Ask a simple question, get a simple answer

Posted: Wed Jan 17, 2018 7:56 pm
by minmay
Yes, LadderComponent is fine to use on minimalSaveState objects.

Re: Ask a simple question, get a simple answer

Posted: Wed Jan 17, 2018 8:33 pm
by bongobeat
Ok, thank you!

Re: Ask a simple question, get a simple answer

Posted: Fri Jan 19, 2018 6:41 pm
by bongobeat
Another "silly" question :mrgreen:

is that possible to define a special wall texts with the minimalSaveState = true?

I mean, to add some text directly in the definition of the objet, and add the minimalthings that it will not be counted in the savegame

e.g: I have a wall text that say "danger" (or anything else), then define an object who got always the "danger" text.

Re: Ask a simple question, get a simple answer

Posted: Fri Jan 19, 2018 9:19 pm
by zimberzimber
You can by having the text components init function set its text to it

Re: Ask a simple question, get a simple answer

Posted: Fri Jan 19, 2018 9:27 pm
by minmay

Code: Select all

defineObject{
  name = "danger_sign",
  baseObject = "base_wall_text",
  components = {
    {
      class = "Model",
      model = "mod_assets/models/danger_sign.fbx",
      staticShadow = true,
    },
    {
      class = "WallText",
      wallText = "Danger!",
    },
  }
  minimalSaveState = true,
}