Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
minmay
Posts: 2697
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay » Mon Jan 01, 2018 12:18 am

No, you leave them in the group. Like this:

Code: Select all

spawn("medusa_2_xaafi_pair",45,15,5,1,0).monstergroup:spawnNow()
for e in Dungeon.getMap(45):entitiesAt(15,5) do
  if e.name == "medusa_2_xaafi" then
    xaafiPremierBoss.bossfight:addMonster(e.monster)
    e.monster:addConnector("onDie","counter_39","decrement")
  end
end
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.

User avatar
akroma222
Posts: 1025
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 » Tue Jan 02, 2018 5:32 pm

Hey All! - I have Q's re: PowerAttackTemplates...
So some specialAttacks are defined manually for each item possessing that specialAttack, eg -
SpoilerShow

Code: Select all

{
			class = "MeleeAttack",
			name = "leech",
			uiName = "Leech",
			attackPower = 20,
			accuracy = 20,
			cooldown = 4.5,
			energyCost = 25,
			swipe = "vertical",
			attackSound = "swipe_light",
			requirements = { "light_weapons", 3 },
			onHitMonster = function(self, monster, side, dmg, champion)
				if monster:hasTrait("undead") then
					-- draining undeads is not wise
					monster:showDamageText("Backlash", "FF0000")
					champion:damage(dmg*0.7, "physical")
					return false
				elseif monster:hasTrait("elemental") or monster:hasTrait("construct") then
					-- elementals are constructs are immune to leech
					monster:showDamageText("Immune")
					return false
				else
					champion:regainHealth(dmg*0.7)
				end
			end,
			gameEffect = "Successful hit drains life from target and heals you.",
		},
.... and then some have been boiled down into: "powerAttackTemplates" to save on repetition (i imagine)
SpoilerShow

Code: Select all

powerAttackTemplates = { "chop",  "cleave",  "devastate", "throw",  "thrust", "flurry", "bash", "stun", "knockback", "volley" }
Question - what exactly happens onInit() if an item has a "MeleeAttackComponent" with a powerAttackTemplate = "flurry" (for example sake?)
Ive run through item.go:componentIterator() after initializing - and it seems that a new component, named after the powerAttackTemplate, is created
The powerAttackTemplate is set to nil after this is done (Im also guessing)
Is there something Im missing or incorrect about here??

Ta! Akroma :)

EDIT: Also! Has anyone got code / definitions for powerAttackTemplates from the vanilla game?? ... that they may share :geek: :P

minmay
Posts: 2697
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay » Tue Jan 02, 2018 9:15 pm

Is this post sufficient?

To recreate flurry you'd do this:

Code: Select all

local c = self.go:createComponent("MeleeAttackComponent","flurry")
c:setAccuracy(20)
c:setAttackPower(self:getAttackPower()/2)
c:setBaseDamageStat(self:getBaseDamageStat())
c:setCooldown(self:getCooldown()*1.5)
c:setEnergyCost(40)
c:setGameEffect("A series of three quick slashes with deadly accuracy.")
c:setPierce(self:getPierce())
c:setRepeatCount(3)
c:setRepeatDelay(0.2)
c:setSwipe("flurry")
c:setUiName("Flurry of Slashes")
if c.go.item:hasTrait("light_weapon") then
	c:setRequirements({light_weapons=4})
elseif c.go.item:hasTrait("heavy_weapon") then
	c:setRequirements({heavy_weapons=4})
end
c.go.item:setSecondaryAction("flurry")
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.

User avatar
akroma222
Posts: 1025
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 » Wed Jan 03, 2018 1:05 am

minmay wrote:Is this post sufficient?
It is most definitely sufficient :D
To recreate flurry you'd do this:

Code: Select all

local c = self.go:createComponent("MeleeAttackComponent","flurry")
c:setAccuracy(20)
c:setAttackPower(self:getAttackPower()/2)
c:setBaseDamageStat(self:getBaseDamageStat())
c:setCooldown(self:getCooldown()*1.5)
c:setEnergyCost(40)
c:setGameEffect("A series of three quick slashes with deadly accuracy.")
c:setPierce(self:getPierce())
c:setRepeatCount(3)
c:setRepeatDelay(0.2)
c:setSwipe("flurry")
c:setUiName("Flurry of Slashes")
if c.go.item:hasTrait("light_weapon") then
	c:setRequirements({light_weapons=4})
elseif c.go.item:hasTrait("heavy_weapon") then
	c:setRequirements({heavy_weapons=4})
end
c.go.item:setSecondaryAction("flurry")
Yup, Id thought and had planned for as much - but that's very handy to have a simple, clean (minmay approved) example!
As always, muchly appreciated 8-) :twisted:

bongobeat
Posts: 966
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat » Wed Jan 03, 2018 1:59 pm

minmay wrote:No, you leave them in the group. Like this:

Code: Select all

spawn("medusa_2_xaafi_pair",45,15,5,1,0).monstergroup:spawnNow()
for e in Dungeon.getMap(45):entitiesAt(15,5) do
  if e.name == "medusa_2_xaafi" then
    xaafiPremierBoss.bossfight:addMonster(e.monster)
    e.monster:addConnector("onDie","counter_39","decrement")
  end
end
Ok, thanks for the code ! ;)
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505

bongobeat
Posts: 966
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat » Thu Jan 04, 2018 9:28 am

Hey all,

I want to create a bomb, lets say a flask of holy water, that do damage only against monsters who have the "undead trait"

Any clue on how to do that ? If it is possible ?

Actually i ve tried something based on a script from zimberzimber. But that don't work correctly for a bomb item.
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505

User avatar
akroma222
Posts: 1025
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 » Thu Jan 04, 2018 12:26 pm

bongobeat wrote:Hey all,

I want to create a bomb, lets say a flask of holy water, that do damage only against monsters who have the "undead trait"

Any clue on how to do that ? If it is possible ?

Actually i ve tried something based on a script from zimberzimber. But that don't work correctly for a bomb item.
Here is a basic framework to work from :)
SpoilerShow

Code: Select all

defineObject{
	name = "bongo_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)
				
				for entity in Dungeon.getMap(level):entitiesAt(x, y) do 		--:allEntities() do
					
					if entity and entity.monster then
						
						if entity.monster:hasTrait("undead") then
						
							local explosion = spawn("fireburst", level, x, y, facing, elevation)
							local power = 55 * self.go.item:getStackSize()
							explosion.tiledamager:setCastByChampion(1)
							explosion.tiledamager:setAttackPower(power)
							
							explosion.particle:setParticleSystem("fireburst")
							explosion.particle:setOffset(vec(0,0,0))
						
							entity.monster:showDamageText("Burn!", "FF0000")
							print(entity.name)
							hudPrint("Burn!")
						else
							print("insert holywater-non-undead fx here")
						end
					end
				end
			end,
			
		},
		
	},
}
EDIT: def includes spawning a burst if undead

bongobeat
Posts: 966
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat » Thu Jan 04, 2018 7:00 pm

Thanks! ;)

this is the final bomb :
I added a bombType, because it always says unknown bombtype in the console, and the fx that I use when thrown on a wall did't show, or I made something wrong. So finally it pops the frost bomb effect.
What I don't understand is that it does more or less damage than the local power.
SpoilerShow

Code: Select all

defineObject{
	name = "holy_water",
	baseObject = "base_item",
	components = {
		{
			class = "Model",
			model = "assets/models/items/flask.fbx",
		},
		{
			class = "Item",
			uiName = "Holy Water",
			gfxIndex = 144,
			description = "A flask of Holy water.",
			impactSound = "impact_blunt",
			stackable = true,
			projectileRotationSpeed = 10,
			projectileRotationZ = -30,
			weight = 0.8,
			traits = { "throwing_weapon", "bomb" },
		},
		{
			class = "ThrowAttack",
			cooldown = 4,
			gameEffect = "Holy water that do deadly damages against Undeads.",
		},
		{
			class = "BombItem",
			bombType = "frost",
			bombPower = 0,
			onExplode = function(self, level, x, y, facing, elevation)
            
            --print(self:getName(), level, x, y, facing, elevation)
            
            for entity in Dungeon.getMap(level):entitiesAt(x, y) do       --:allEntities() do
               
               if entity and entity.monster then
                  
                  if entity.monster:hasTrait("undead") then
                  
                     local explosion = spawn("fireburst", level, x, y, facing, elevation)
                     local power = 150 * self.go.item:getStackSize()
                     explosion.tiledamager:setCastByChampion(1)
                     explosion.tiledamager:setAttackPower(power)
                     
                     explosion.particle:setParticleSystem("shadowraze")
                     explosion.particle:setOffset(vec(0,0,0))
                  
--                     entity.monster:showDamageText("Burn!", "FF0000")
--                     print(entity.name)
--                   hudPrint("Burn!")
                  else
--explosion.particle:setParticleSystem("blob")
--			print("insert holywater-non-undead fx here")
                  end
               end
            end
         end,
		},
	},
	tags = { "weapon", "weapon_throwing" },
}
shadowraze particles : it comes from Zimberzimber asset, its principally for the soul_stealer weapon.
SpoilerShow

Code: Select all

defineParticleSystem{
	name = "shadowraze",
	emitters = {

		-- fog
		{
			spawnBurst = true,
			maxParticles = 50,
			sprayAngle = {0,360},
			velocity = {1,2},
			objectSpace = true,
			texture = "assets/textures/particles/fog.tga",
			lifetime = {1,1.2},
			color0 = {0.01, 0.01, 0.01},
			opacity = 1,
			fadeIn = 0.05,
			fadeOut = 0.3,
			size = {1, 2},
			gravity = {0,0,0},
			airResistance = 0.5,
			rotationSpeed = 1,
			blendMode = "Translucent",
		},
		
		-- flames
		{
			spawnBurst = true,
			maxParticles = 50,
			sprayAngle = {0,360},
			velocity = {1,1.25},
			objectSpace = true,
			texture = "assets/textures/particles/torch_flame.tga",
			frameRate = 35,
			frameSize = 64,
			frameCount = 16,
			lifetime = {0.4,0.6},
			color0 = {5, 0, 0},
			opacity = 0.75,
			fadeIn = 0.1,
			fadeOut = 0.3,
			size = {0.4, 0.6},
			gravity = {0,0,0},
			airResistance = 0.5,
			rotationSpeed = 2,
			blendMode = "Additive",
			depthBias = 0.02,
		},

		-- stars
		{
			spawnBurst = true,
			maxParticles = 100,
			sprayAngle = {0,360},
			velocity = {3,5},
			objectSpace = false,
			texture = "assets/textures/particles/teleporter.tga",
			lifetime = {0.7,1},
			color0 = {10,0.1,0.1},
			opacity = 0.05,
			fadeIn = 0.01,
			fadeOut = 0.1,
			size = {0.1, 1},
			gravity = {0,0,0},
			airResistance = 1,
			rotationSpeed = 5,
			randomInitialRotation = true,
			blendMode = "Translucent",
			depthBias = 0.025,
		},
	}
}
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505

User avatar
zimberzimber
Posts: 432
Joined: Fri Feb 08, 2013 8:06 pm

Re: Ask a simple question, get a simple answer

Post by zimberzimber » Sat Jan 06, 2018 9:00 pm

That script will spawn a fireburst for *every monster* on the hit tile. Works with single monsters, yes. But not so much with monster groups + rat swarm likes...

There's no method for directly damaging a monster IIRC, so you gotta modify their health manually (and do death checks, resistances, etc...)
Function from my asset pack:

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
My asset pack [v1.10]
Features a bit of everything! :D

bongobeat
Posts: 966
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat » Tue Jan 09, 2018 4:16 pm

zimberzimber wrote:That script will spawn a fireburst for *every monster* on the hit tile. Works with single monsters, yes. But not so much with monster groups + rat swarm likes...

There's no method for directly damaging a monster IIRC, so you gotta modify their health manually (and do death checks, resistances, etc...)
Function from my asset pack:

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
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?
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505

Post Reply