[ASSET] - DM SKELETON RAISING FROM COFFIN

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

Re: [ASSET] - DM SKELETON

Post by JKos »

You don't actually need the full LoG Framework if you just want to use timers-script entity.

Just copy-paste the script below to a script entity named timers
Documentation is here: https://sites.google.com/site/jkosgrimr ... ule-timers

And this way you can safely destroy the object from it's onDie-hook (I have used this method in orrr2 so it works):

Code: Select all

onDie(self)
   timers.delayCall(0.1,function(id) 
            local e = findEntity(id)
            if  e then  e:destroy() end
            ---spawn your monster here
         end,
         {self.id}
      )
end
timers script entity

Code: Select all

objects = {}
debug = false
count = 0

function _countUp()
	count = count + 1
end


-- spawn a new timer

function create(self,id,plevel)
 plevel = plevel or party.level
 id = id or 'fw_extended_timer_'..timers.count
 timers._countUp()

 local timerEntity = spawn('timer',plevel,0,0,1,id)
 id = timerEntity.id
 self.objects[id] = wrap(timerEntity)
 timerEntity:addConnector('activate','timers','callCallbacks')
 return self.objects[id]
end

-- find extended timer
function find(self,id)
	return self.objects[id]
end

-- simple delayed function call
function delayCall(interval,callback,args)
	return timers:create()
	:setTimerInterval(interval)
	:setTickLimit(1,true)
	:addCallback(callback,args,true)
	:activate()
end

-- repeated function call
function repeatCall(interval,count,instant,callback,args)
	return timers:create()
	:setTimerInterval(interval)
	:setTickLimit(count,true)
	:addCallback(callback,args,true)
	:setInstant(instant)
	:activate()

end

-- sequential function call
function sequenceCall(seq,callback,args)
	return timers:create()
	:setSequence(seq,true,true)
	:addCallback(callback,args,true)
	:activate()
end


function setLevels(self,levels)
	print('timers:setLevels is deprecated, you can remove the function call.')
end


-- create a wrapper object to timer passed as argument
function wrap(timer)
 local wrapper = {
    id = timer.id,
	level = timer.level,
    interval = 0,
    connectors = {},
	active = false,
	callbacks = {},
	tick = 0,
	addConnector = timers._addConnector,
	activate = timers._activate,
	deactivate = timers._deactivate,
	toggle = timers._toggle,	
	isActivated = timers._isActivated,		
	setInstant = timers._setInstant,
	setTimerInterval = timers._setTimerInterval,
	setConstant = timers._setConstant,
	destroy = timers._destroy,	
	addCallback = timers._addCallback,
	callCallbacks = timers.callCallbacks,
	setTickLimit = timers._setTickLimit,
	reset = timers._reset,
	setSequence = timers._setSequence,
	tickFilter = {},
	addTickCallback = timers._addTickCallback,
 }
 return wrapper
end

function _addConnector(self,paction,ptarget,pevent)
	self:addCallback(
		function(self,scriptId,functionName) 
			findEntity(scriptId)[functionName](self)
		end,
		{ptarget,pevent}
	)
	return self
end

function _activate(self)
	    self.active = true
		if self.isConstant then
			timers.objects[self.id..'_'..party.level]:activate()
		else
			findEntity(self.id):activate()
		end
		if self.instant then
			self:callCallbacks()
		end
		return self
end

function _deactivate(self)
	    self.active = false

		findEntity(self.id):deactivate()
		
		if (self.isConstant) then
			for l=1, getMaxLevels() do
				timers.objects[self.id..'_'..l]:deactivate()
			end
		end		
		if (type(self.onDeactivate) == 'function') then
			self.onDeactivate(self)
		end		
		return self
end

function _toggle(self)
		if (self.active) then 
			self:deactivate()
		else
			self:activate()
		end
		return self
end

function _isActivated(self)
		return self.active
end
-- If set, callbacks are called instantly after the activation of the timer.
function _setInstant(self,bool)
		self.instant = bool
		return self
end

function _setTimerInterval(self,interval)
	    self.interval = interval  + 0
		findEntity(self.id):setTimerInterval(self.interval)
		return self
end

function _setSequence(self,seq,runOnce,autodestroy)
	if type(seq) == 'string' then
		print('sequence must be in table form')
	end
	self.seq = seq
	self:setTimerInterval(seq[1])
	if runOnce then
		self:setTickLimit(#seq,autodestroy)
	end
	return self
end

function _setConstant(self)
		self.isConstant = true
		timers.copyTimerToAllLevels(self)
		return self
end

function _destroy(self)
		findEntity(self.id):destroy()
		timers.objects[self.id] = nil
		
		if (self.isConstant) then
			for l=1,getMaxLevels() do
				timers.objects[self.id..'_'..l]:destroy()
			end
		end
		if (type(self.onDestroy) == 'function') then
			self.onDestroy(self)
		end		
		return self
end

function _reset(self,dontResetTick)
	if self.isConstant then
		print("Can't reset constant timer yet")
		return
	end
	self:deactivate()
	findEntity(self.id):destroy()
	local timerEntity = spawn('timer',self.level,0,0,1,self.id)
	timerEntity:addConnector('activate','timers','callCallbacks')
	if not dontResetTick then
		self.tick = 0
	end
	return self
end

function _addCallback(self,callback,callbackArgs,dontPassTimerAsArgument)
		if type(callbackArgs) ~= "table" then 
			callbackArgs = {callbackArgs}  
		end
		callbackArgs = callbackArgs or {}
		
		self.callbacks[#self.callbacks+1] = {callback,callbackArgs,dontPassTimerAsArgument}
		return self
end

function _addTickCallback(self,tick,callback,callbackArgs)
	self:addCallback(callback,callbackArgs)
	if not self.tickFilter[#self.callbacks] then self.tickFilter[#self.callbacks] = {} end
	self.tickFilter[#self.callbacks][tick] = true  
	return self
end

function _setTickLimit(self,limit,autodestroy)
		self.limit = limit
		self.autodestroy = autodestroy
		return self
end	

function callCallbacks(timerEntity)

	local extTimer = objects[timerEntity.id]
	extTimer.tick = extTimer.tick + 1
	
	for n,callback in ipairs(extTimer.callbacks) do
		
		local call = true
		if extTimer.tickFilter[n] and extTimer.tickFilter[n][extTimer.tick] == nil or extTimer.destroyed == true then
			call = false
		end
		if call then
			if callback[3] then
				callback[1](unpack(callback[2]))
			else
				callback[1](extTimer,unpack(callback[2]))
			end
		end
	end

	if extTimer.limit and extTimer.tick >= extTimer.limit then
		extTimer:deactivate()
		if (extTimer.autodestroy) then
			-- mark as destroyed
			extTimer.destroyed = true
		end		
	end 

   -- handle sequences
	if  extTimer.active and extTimer.seq then
		local interval = extTimer.seq[extTimer.tick+1]
		if interval ~= nil then
			extTimer:reset(true)
		else
			interval = extTimer.seq[1]
			extTimer:reset()
		end
		extTimer:setTimerInterval(interval)
		extTimer:activate()
		
	end		

	
	if (extTimer.destroyed) then
		if timers.debug then print('timer '..extTimer.id..' destroyed') end
		extTimer:destroy()
	end
end

function copyTimerToAllLevels(self)

		for l=1, getMaxLevels() do
		
			local t = timers:create(self.id..'_'..l,l)
			
			-- if interval is larger than 1 second
			-- use 0.1 seconds interval and count to actual interval*10
			-- this way the gap between level changes should stay minimal
			-- Thanks to Batty for the idea 
			if self.interval >= 1 then
				t:setTimerInterval(0.1)
				self.count = 0
				t:addCallback(
					function(self,timer_id,interval) 					
						local timer = timers.objects[timer_id]
						if (self.level == party.level) then
							timer.count = timer.count + 1
						else
							self:deactivate()
							timers:find(timer_id..'_'..party.level):activate()
						end
						if (timer.count == interval*10) then
							timer:callCallbacks()
							timer.count = 0
						end
		
					end,
					{self.id,self.interval}
				)
			else
				t:setTimerInterval(self.interval)
				t:addCallback(
					function(self,timer_id) 					
						local timer = timers.objects[timer_id]
						if (self.level == party.level) then	
							timer:callCallbacks()
						else
							self:deactivate()
							timers:find(timer_id..'_'..party.level):activate()
						end
					end,
					{self.id}
				)
			end
					
		end	
		self:deactivate()
end
Edit: oh, you wanted to do this without script-entities, I'm afraid that it's not possible.
- 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
Leki
Posts: 550
Joined: Wed Sep 12, 2012 3:49 pm

Re: [ASSET] - DM SKELETON

Post by Leki »

Ok, last days I was looking for solution but it's impossible to achieve it without ingame script - it means I will leave the idea to make skeleton jumping out from the coffin. Only thing I can do is to create "big coffin" - defined as a lever - you can open it and on toggle there will be random - spawn monster or not - but I did some tests and it does not look good - the coffin must be placed in the center of the cell and must be big and you also must place walls around etc... I really hate the limitations we have with simple things like this, especially when you can see it here:
SpoilerShow
Image


Hope LoG 2 will be more fiendly... :roll:
So - if you wanna skeleton, let me know, I will pack it and share download link. I will also pack and send DM version (falchion and wooden shield) to Germanny, so if you want it, ask him for sharing - he will improve some textures etc.


OT a little bit, but I wanna share my fresh experience:
I'm downloading MMXL right now... Really funny thing is that they "support" mod comunity, published asset pack, made video how to mod the game etc...
The only glich is that you need Unity Pro for that which cost 1500USD... But you can use 30trial for that - yes it's official advice from their's MODDING GUIDE... Omg :shock:

So i tried my normal Unity and after a hour of preparing of the project it works in some way. The Modding Kit itself will not fully run with the Unity free version. The main reason is that the core feature which is used for the export of the 3D environment is a Unity Pro and thinks like calculating lighs, oclusion maps etc... I am allmost sure the problem will also appear in navigation, because it looks that they use navmesh which is part of Unity Pro... So, true support for mod cimunity :?

Then I read this:
Aside from the 3D environment export issue, the Modding Kit should work fine with Unity free. This means that you can create, edit, and save levels in the normal scene structure of Unity. These can then be exchanged with friends. So if you have a contact who has access to Unity professional, he can make the exports for you if you share your source files. The exported files are required to load your Mod in the game...
Send? Friends? Export? WTF? I will send unity scenes to the friens, they wil export it and send back to me, I will load it into the game and after Logos, loading etc I will see that encounter shall be one fcuking cell left?

Anyway, I spent some time with the editor and it's terible experience. You need a lot of skills to "make something" - I mean to get objects into the engine. Updating of scene is slow, you cannot tune it in dynamic way - you have to work with unity prefabs etc, there is a grid, but no for visual, only for triggers, events etc... It's only tool layer over the scene... in other words, be happy you have LoG editor. God bless John for GMT and wallasaurus for maxscript, we no need more. It's crazy to achieve something in LoG, but still 100x better if you compare it with MMX Tools. Just look into documentation and compare it with LoG modding page...

Well - ok, It's the first impression - maybe it's ok, but not for me, I guess. After few hours I was happy when I close it. Hope comunity will make some "new modding tools" for MMX, but I am afraid that Unity Pro will kill it. And tThere is also one very important thing - you have to export scene to play it - or I din't find the way to run game in editor - it's not possible I guess, because there is only scene, but not the game logic in "editor"... But I still hope the game will be good... I look forward to try it... especially when they anounced first DLC :evil:
I'm the Gate I'm the Key.
Dawn of Lore
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [ASSET] - DM SKELETON

Post by Diarmuid »

I'm using Unity also for developping my game (http://darkdale.net) and I ran into that specific issue. I did consider their solution, but rejected it very rapidly as it's very very poor in my opinion. Unity is not an editor for amateurs to make mods, it's a full complex professionnal game engine. Also "ask a friend with Unity Pro" to make it for you", I'm not even sure if this is OK license-wise.

So I actually went on coding an entire custom Dungeon Editor in Unity, for a modding experience similar to LoG. You can see a glimpse of the editor here : https://vimeo.com/75113810. Of course, that meant that levels had to be generated on the fly, and I couldn't use built-in light-bakinging/nav-mesh solutions and had to reproduce a lot of Unity functions to make it work with external .lua files, which my editor outputs. Yes, I also went out of my way to provide Lua support, as I find it way more modder-friendly than C# or the "unity javascript". But seeing how modding could be a powerful experience here, for me ensuring proper modding capabilities was prioritary.
chaoscommencer
Posts: 119
Joined: Sun Jan 05, 2014 7:48 pm

Re: [ASSET] - DM SKELETON

Post by chaoscommencer »

You made that editor? That's pretty impressive man, nice job. Does DarkDale use the same building blocks as LoG (eg. square units of movement around the map, with set tilesets)? Or are you free to move in any direction like Skyrim?
Working on a dungeon that displays a massive collection of assets while sorting them into convenient reusable plugin format (concept from some of leki's mods). Will contribute some of my own models as well eventually and follow that with custom dungeon.
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [ASSET] - DM SKELETON

Post by Diarmuid »

chaoscommencer wrote:You made that editor? That's pretty impressive man, nice job. Does DarkDale use the same building blocks as LoG (eg. square units of movement around the map, with set tilesets)? Or are you free to move in any direction like Skyrim?
Thanks. It's tile-based, not free movement. Think of it as LoG with quests, shops and NPCs if you wish. ;)

But I've halted the development a bit lately as I'm trying to wrap up the ORRR2 project in the last month or so, as soon as that's ready, I'm getting back to it.
chaoscommencer
Posts: 119
Joined: Sun Jan 05, 2014 7:48 pm

Re: [ASSET] - DM SKELETON

Post by chaoscommencer »

That's cool; yes, it's definitely too bad Grimrock didn't come with some of those features as well, but I guess it didn't need them for its setting. Everyone's excited for ORRR2 :)
Working on a dungeon that displays a massive collection of assets while sorting them into convenient reusable plugin format (concept from some of leki's mods). Will contribute some of my own models as well eventually and follow that with custom dungeon.
lexdr
Posts: 108
Joined: Thu Dec 26, 2013 3:29 pm
Location: France

Re: [ASSET] - DM SKELETON

Post by lexdr »

Hi Leki, is the DM skeleton available for download?
:)
User avatar
germanny
Posts: 530
Joined: Sat Apr 07, 2012 10:52 pm
Location: Kiel, Germany

Re: [ASSET] - DM SKELETON

Post by germanny »

I´m very pleased if you will send me the falchion skeleton version!
Will it be ok for you if it pops into the Dm remakes?
I promised to make some custom textures as well.
Cool work as usual!
PM me, Leki.
Dungeon Master Resource Pack worker and passionated Beer drinker
Aeon
Posts: 31
Joined: Sun Mar 04, 2012 5:12 pm
Location: Rhineland, Germany

Re: [ASSET] - DM SKELETON

Post by Aeon »

Glad you´re back at the monsters, there happened not much in this field when looking around! Can´t wait to try out your skeleton, looks absolutely great already. And we can´t get enough of new enemies, can´t we? :-D
User avatar
Leki
Posts: 550
Joined: Wed Sep 12, 2012 3:49 pm

Re: [ASSET] - DM SKELETON

Post by Leki »

Sorry guys, I'm very occupied last days because of some RL issues - it's about idea of some company who wanna build 130 000 Tons/year vaste recycling/junkyard facility 300 meters from our neighborhood :x We already won first round but it's not over yet...
So I only checking forum from time to time what's new, but I completly stopped all my work and activities until I solve this RL sh*t...

I sent Dm skeleton to germanny, he will handle it and make and share propper plugins (I guess one as DM version with falchion and wooden shield for his stuff) and one with LoG shield and sword free for all, so you can look forward for it.
I'm the Gate I'm the Key.
Dawn of Lore
Post Reply