Adding methods to monsters

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Adding methods to monsters

Post by Diarmuid »

Hi there,

A quick question to coders around with more experience than me. Is there a neat way to add methods to a monster?

For example, I developped a function which can freeze a monster (real blue freeze) at will for a duration. Right now, I have it called by:

Code: Select all

exsp.freezeMonster(monster, duration)
However, I would love to have this as monster:freeze(duration). I know I can make a wrapper for it, and have it called by:

Code: Select all

exsp.extend(monster):freeze(duration)
or

Code: Select all

monster = exsp.extend(monster)
monster:freeze(duration)
Now, is it worth it? Which version is more legible and user-friendly, the function or the method?
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Adding methods to monsters

Post by undeaddemon »

I don't know what any of that means... but I know I like it.
User avatar
HaunterV
Posts: 676
Joined: Mon Apr 16, 2012 9:54 pm
Location: Barrie, Ontario, Canada

Re: Adding methods to monsters

Post by HaunterV »

is this a way of adding new abilities to monsters? someone inject some idiot into this thread so I can understand it, because as it stands right now, I'm stumped.
Grimrock Community 'FrankenDungeon 2012. Submit your entry now!: http://tinyurl.com/cnupr7h
SUBMIT YOUR ASSETS! Community Asset Pack (C.A.P.): http://tinyurl.com/bqvykrp
Behold! The HeroQuest Revival!: http://tinyurl.com/cu52ksc
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Adding methods to monsters

Post by Diarmuid »

HaunterV wrote:is this a way of adding new abilities to monsters? someone inject some idiot into this thread so I can understand it, because as it stands right now, I'm stumped.
Yes, I have a whole new monster module in the next version of exsp, with tons of new stuff:
monster:hold(duration)
monster:unhold()
monster:isHeld()
monster:onUnhold(function(self))
monster:freeze(duration)
monster:isFrozen()
monster:onUnfreeze(function(self))
monster:makeInvulnerable(duration)
monster:unmakeInvulnerable()
monster:isInvulnerable()
monster:onUnmakeInvulnerable(function(self))

I just have to figure how to implement this so that it's the easier to use by everyone. After rethinking a bit after I posted, I think I'll go with the method route, it will be more expandable and consistent with current way scripting works in LoG.
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Adding methods to monsters

Post by undeaddemon »

[embarrassed to the point tears..]

Check Boxes?

:P
User avatar
msyblade
Posts: 792
Joined: Fri Oct 12, 2012 4:40 am
Location: New Mexico, USA
Contact:

Re: Adding methods to monsters

Post by msyblade »

Do it Diarmuid. Checkboxes. You know u can, you know it's the next step of functionality. Do it. Checkboxes :)
Currently conspiring with many modders on the "Legends of the Northern Realms"project.

"You have been captured by a psychopathic diety who needs a new plaything to torture."
Hotel Hades
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Adding methods to monsters

Post by Diarmuid »

Checkboxes? I feel like I'm missing the joke... :)
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

Re: Adding methods to monsters

Post by JKos »

There is now way to add methods to entities, but you can fake it like I did with extended timer, see the sources. Actually I have been thinking this too, but didn't have the time to implement it.


the basic idea is like this:

Code: Select all

function wrap(monster)
 local wrapper = {
    id = monster.id,
    level = monster.level,
    x = monster.x,
    y = monster.y,
    getLevel = function(self)
       return findEntity(self.id):getLevel()
    end,
   freeze(self)
      ...freeze monster...
   end
 }
 return wrapper
end
- LoG Framework 2http://sites.google.com/site/jkoslog2 Define hooks in runtime by entity.name or entity.id + multiple hooks support.
- cloneObject viewtopic.php?f=22&t=8450
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Adding methods to monsters

Post by Diarmuid »

Yes, that's exactly what I did. I stared blankly at your timers code for like three hours and then suddenly understood how tables could be objects...

Here's the code I made:

Code: Select all

function extend(entity)
	if not(entity) then return nil end
	objects[entity.id] = {}
	objects[entity.id].name = entity.name
	objects[entity.id].id = entity.id
	objects[entity.id].level = entity.level
	objects[entity.id].x = entity.x
	objects[entity.id].y = entity.y
	objects[entity.id].facing = entity.facing
	objects[entity.id].class = entity.class
	return addExtendedMethods(objects[entity.id])
end

function addExtendedMethods(object)
	local methods
	if object.class == "Monster" then
		methods = {
			-- Default Grimrock methods
			setAIState = function(self, state)
				findEntity(self.id):setAIState(state)
			end,
			setHealth = function(self, health)
				findEntity(self.id):setHealth(health)
			end,
			getHealth = function(self)
				return findEntity(self.id):getHealth()
			end,
			setLevel = function(self, level)
				findEntity(self.id):setLevel(level)
			end,
			getLevel = function(self)
				return findEntity(self.id):getLevel()
			end,
			setPosition = function(self, x, y, level, facing)
				findEntity(self.id):setPosition(x, y, level, facing)
			end,
			addItem = function(self, item)
				findEntity(self.id):addItem(item)
			end,
			destroy = function(self)
				findEntity(self.id):destroy()
			end,
			-- Extended methods
			hold = exsp._hold,
			unhold = exsp._unhold,
			isHeld = exsp._isHeld,
			onUnhold = exsp._onUnhold,
			freeze = exsp._freeze,
			unfreeze = exsp._unfreeze,
			isFrozen = exsp._isFrozen,
			onUnfreeze = exsp._onUnfreeze,
			makeInvulnerable = exsp._makeInvulnerable,
			unmakeInvulnerable = exsp._unmakeInvulnerable,
			isInvulnerable = exsp._isInvulnerable,
			onUnmakeInvulnerable = exsp._onUmakeInvulnerable,
			move = exsp._move,
			addMonsterHooks = exsp.addMonsterHooks,
			executeMonsterHooks = exsp.executeMonsterHooks,
		}
	else
		return nil
	end
	for k, v in pairs(methods) do
		object[k] = v
	end
	return object
end
My main issue was that the wrapper was not dynamic for level, x, y, facing. Then I did some research and found about metatables, and was like, YEEEEES!!!!! and then saw Legend of Grimrock didn't support them and went NOOOOOO...

But I had a very fast timer (0.05) detecting spells in the dungeon running anyway, so I put the following code inside:

Code: Select all

		for id, object in pairs(objects) do
			if findEntity(id) then
				object.level = findEntity(id).level
				object.x = findEntity(id).x
				object.y = findEntity(id).y
				object.facing = findEntity(id).facing
			else
				object = nil
			end
		end
That way the dynamic properties are really updated in (almost) real time, and if the monster dies, the extended object is deleted instantly as well.

Thus:

Code: Select all

local monster = exsp.extend(snail_1)
print(monster.x, monster.y)
Will always return the true current x and y properties. So now monster objects can be "extended" and used in scripts exactly like normal monster objects, but with new methods and the advantage that you can store them in variables without serialization errors.

I also plan to extend other things, like Projectiles, so I made the exsp.extend wrapper flexible.
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Adding methods to monsters

Post by Komag »

You can put code linked in the new gui hook and it will run "every frame" if I understand how it works properly, so it might be more reliable than a 0.05s timer
Finished Dungeons - complete mods to play
Post Reply