Page 2 of 4

Re: blocker for party?

Posted: Thu Jan 24, 2013 1:55 am
by vidarfreyr
That is clever Pandafox. Thanks for sharing.

Re: blocker for party?

Posted: Sun Feb 10, 2013 10:02 am
by akroma222
Very useful and interesting!
Panda, the ghosty texture you have used for the skeleton... where may I find this??
Its ghost making time :)

Re: blocker for party?

Posted: Sun Feb 10, 2013 11:31 am
by Pandafox
akroma222 wrote:Very useful and interesting!
Panda, the ghosty texture you have used for the skeleton... where may I find this??
Its ghost making time :)
hi,

I made the ghost skeleton. Not shared yet...
I will share all the things I made after the release of my new dungeon (probably the next days... It is finished, I am testing it now) ;)

Re: blocker for party?

Posted: Fri Feb 15, 2013 3:46 pm
by akroma222
No dramas at all! :)

Re: blocker for party?

Posted: Fri Feb 15, 2013 7:17 pm
by Neikun
I think you could do it by setting the regular skeleton material to Additive, no?

Re: blocker for party?

Posted: Fri Feb 15, 2013 8:33 pm
by akroma222
Indeed, that is what LG has suggested... using a slime texture...
I will investigate, but first up is getting this new spell system up and running

I will contact you soon Neikun regarding skype and the northern realms, sorry about my absence ;)

Re: blocker for party?

Posted: Fri Feb 15, 2013 11:54 pm
by Neikun
No worries. I'm still just as excited as I was before to have you on board.

Re: blocker for party?

Posted: Sat Feb 16, 2013 11:58 am
by Pandafox
I published the ghost skeleton because anyway you saw it here, then, no surprise in my mod ;)
http://grimrock.nexusmods.com/mods/198

Re: blocker for party?

Posted: Sat Feb 16, 2013 6:13 pm
by Marble Mouth
Hi Pandafox. This is a really neat idea, and you got me thinking. I implemented a different approach to "conditional blocker":
SpoilerShow
objects.lua

Code: Select all

cloneObject{
	name = "conditionalBlocker",
	baseObject = "torch_holder",
    model = "assets/models/env/dungeon_wall_01.fbx",
    onInsertItem = function()
        return false
    end,
    editorIcon = 120,
}

cloneObject{
	name = "twoWayConditionalBlocker",
	baseObject = "torch_holder",
    model = "assets/models/env/dungeon_wall_01.fbx",
    onInsertItem = function()
        return false
    end,
    editorIcon = 120,
}
init.lua

Code: Select all

cloneObject{
   name = "party",
   baseObject = "party",

   onMove = function( self , dir )
        return partyScript.canMove( self , dir )
   end,

   onAttack = function( self , weapon )
        return partyScript.canAttack( self , weapon )
   end,
}
script_entity named partyScript

Code: Select all

canMove = function ( self , dir )
	for entity in entitiesAt( self.level , self.x , self.y ) do
		if blockerScript.isBlocker( entity ) and 
		entity.facing == dir then
			return false
		end
	end
	return true
end

canAttack = function ( champion , weapon )
	for entity in entitiesAt( party.level , party.x , party.y ) do
		if blockerScript.isBlocker( entity ) and 
		entity.facing == party.facing then
			return false
		end
	end
	return true
end
script_entity named utilityScript

Code: Select all

allEntities = function( level )

	local s = {}
	s["offset"] = 0
	local c = 0
    for i=0,31 do
    	for j=0,31 do
             for k in entitiesAt(level,i,j) do
                c = c + 1
                s[c] = k
             end
        end
    end

    local f = function ( s , v )

        local offset = s["offset"] + 1
        s["offset"] = offset
          
        return s[offset]
    end

    return f , s , nil
end

getXYFromDir = function ( dir )
	if dir == 0 then
		return 0 , -1
	elseif dir == 1 then
		return 1 , 0
	elseif dir == 2 then
		return 0 , 1
	elseif dir == 3 then
		return -1 , 0
	end
end
Why did I redefine allEntities?
getXYFromDir is just the same function that others have called getForward . Maybe I should use the standard name for the sake of consistency?

script_entity named blockerScript

Code: Select all

allEntities = utilityScript.allEntities

do --setup a duplicate for each twoWayConditionalBlocker
	local twoWays = {}
	local c = 0
	local maxDungeonLevel = 1

	for level = 1,maxDungeonLevel do
		for entity in allEntities( level ) do
			if entity.name == "twoWayConditionalBlocker" then
				c = c + 1
				twoWays[c] = entity
			end
		end
	end
	
	for i , v in ipairs( twoWays ) do
		local x , y = utilityScript.getXYFromDir( v.facing )
		x = x + v.x
		y = y + v.y
		spawn( "twoWayConditionalBlocker" , v.level , x , y ,
		 ( v.facing + 2 ) % 4 )
	end
end

blockers = { "conditionalBlocker" , 
			 "twoWayConditionalBlocker" ,}
reverseBlockers = {}
for i , v in ipairs( blockers ) do
	reverseBlockers[v] = i
end
			
isBlocker = function ( entity )
	return reverseBlockers[entity.name]
end
If you place a twoWayConditionalBlocker in the editor, then the blockerScript will automatically create a duplicate in the adjacent tile facing the opposite way (when you begin preview or play.) You should adjust the line "local maxDungeonLevel = 1" in blockerScript to suit your dungeon. If you place a conditionalBlocker, then it will only render and block movement one way (but looking at it from the other side produces some weird graphical effects.)

Undocumented feature used: torch_holder supports onInsertItem just like alcove.

This version of blockerScript doesn't get a huge benefit out of the setup of blockers and reverseBlockers , but this setup does make it very easy to expand the list of blockers. If you add more blocker type objects, just expand the list of names in blockers.
As compared to your method:

1. Monsters can attack through conditionalBlocker and twoWayConditionalBlocker. If you want to disallow this, then give the monster an onAttack hook similar to the party's onAttack hook. They can't attack through your walls (although a ranged enemy could if the party wasn't adjacent to the wall - see point 4.)
2. Editor placement. You just place these items like you place torch_holder. The editor wants you to place them against walls, but you can always add/remove walls as you go, or you could place them and then move them around with QWEASD. I found this somewhat easier than following the naming scheme that your method required.
3. Normally, if the party tries to move into an obstructed square, they get visual feedback that they started to move in that direction but couldn't complete the movement. With these items, they just don't move at all. Similarly, the party doesn't even punch the wall if they try to attack while facing a blocker, to prevent hitting the monster on the other side. A savvy player could use these quirks to determine where the "fake" walls are. Your walls don't have this problem.
4. You can always throw items through my blockers. I haven't come up with a great way to prevent this. With yours, you can throw an item through it from a distance, but not if you are standing right next to it.
5. It's easy to add an onMove hook to individual monsters ( just copy the party's onMove code.) This allows you to let some monsters pass through (like ghosts) while other monsters are blocked just like the party. With your pressure plate method, each plate either is triggered or is not triggered by monsters, so it's more difficult to conditionalize which monsters get blocked by which blockers.
6. I haven't figured out a good way to deal with the party casting spells. I don't want to prevent them casting self targeting spells while they're facing the blocker, but I do want to prevent them casting spells that would pass through the blocker. Ideally, casting fireburst while facing a blocker would damage the party, just as it does while facing a real wall. You could always take the cop out and use anti-magic zones to avoid dealing with this.
7. As a quirk of my implementation, in the editor you can place a torch "in" the conditionalBlocker. I disabled placing torches in game. If you try, then you just throw the torch through ( see point 4. )
8. Monsters can still see through my blockers. Even if they have onMove and onAttack hooks so that the blockers will block them, their AI will always try to move and attack through the blockers if they see the party on the other side.

Some of these differences you may consider as advantages, some as disadvantages. Mostly, I'm just posting what I have to keep the ideas flowing.

Re: blocker for party?

Posted: Wed Mar 20, 2013 5:18 pm
by SpiderFighter
(I know this thread is older, but this seems to be a reccurring question/request, and it would be great to have something we can consistantly point to.)

It still surprises me that, with all the other options available to modify/affect the party, there's not a partyBlocker (similar to the in-editor Blocker that we can enable/disable) or a setMovement(true/false) command. No idea is foolproof, that my simple non-lua-oriented mind can grasp. The easiest way would be to clone an item (such as mole_jerky), make it impossibly heavy, and Champion:insertItem /Champion:removeItem...but then there's nothing to stop the player from removing it themselves, causing a potential crash when the script tries to remove it (or when the script tries to place it in a full pack).

Back in the oldschool days, I made a ST:TNG mod for Wolf3D, where enemies would vapourize when the player killed them. Only, Wolf3D wouldn't allow a completely invisible tile/sprite. So, I made an invisible sprite with one pixel on the bottom that matched the color of the floor the closest. If you knew it was there, you could see it, but most people didn't notice, and the effect was pretty good. Now, I see that some of the custom assets for LoG still have physical, but not visual, height; that is, the player can place an item on top of a bed, and it will appear to be hovering several feet above it. All of this leads me to wonder if the same kind of thing can't work here: create a custom asset called "party_blocker," make it almost completely invisible (or completely invisible if that's possible), then set it as a "Blockage." Then the designer could simply drop it in and remove it again when needed. Would it work?