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: 2789
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

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: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 »

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: 2789
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

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: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 »

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: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat »

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: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat »

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: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 »

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: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat »

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 »

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: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat »

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