Tentative changelist for 2.1.19
- Dr.Disaster
- Posts: 2876
- Joined: Wed Aug 15, 2012 11:48 am
Re: Tentative changelist for 2.1.19
Thx Issac for reminding me of this issue.
The effect of the Rage potion can be stacked without limit: drinking X Rage potions adds 20 times X Strength to a character.
The effect of the Rage potion can be stacked without limit: drinking X Rage potions adds 20 times X Strength to a character.
Re: Tentative changelist for 2.1.19
Would it be possible to get conformation from AH that this setting of "seesParty" when it shouldn't be set is indeed a bug? Or any other suggestions to stop it from happening. It is a very serious bug for my plans of doing a custom AI. I have a whole new path finding algorithm working and my intention is to use this when the party is not seen. But if "seesParty" is going to true when the party is behind walls, this design will fail. I am basically dead in the water with my AI plans without a fix or workaround to this problem. Thanks.MrChoke wrote:Hi. I didn't know about sparse. I did try it though and the problem is still happening. To ensure that it was not any mistake I made with custom objects, I replaced all of them with "castle_door_wood". This is not a sparse door. The "seesParty" property will still go to true for one move and then back to false. It seems to do it only at perfect or close to perfect diagonals to the party, never at horizontal or vertical positions.petri wrote:I think you doors are 'sparse'MrChoke wrote:Ugh. I just confirmed a bug. Its in the Brain component, the "seesParty" property. It is erroneously getting set to true even though the party should not be seen. It doesn't appear to fail if there is a solid wall blocking. However, it does fail for walls with door components, even if multiple of these block the party. When it fails, it will go to true for one movement of the monster and then go back to false. I cannot pinpoint why it is doing it only that it clearly shouldn't be.
I also see if I put a sold wall tile in the perfect diagonal direction, it stops happening.
Re: Tentative changelist for 2.1.19
It works for me. Maybe you are trying to access the brain outside the onThink hook? The senses of monsters are updated just before their brain is updated.MrChoke wrote:Would it be possible to get conformation from AH that this setting of "seesParty" when it shouldn't be set is indeed a bug?
Re: Tentative changelist for 2.1.19
Thanks for looking into this. To make sure we are both seeing the exact same thing, below is a very simple test dungeon I made specifically to show you the issue.petri wrote:It works for me. Maybe you are trying to access the brain outside the onThink hook? The senses of monsters are updated just before their brain is updated.MrChoke wrote:Would it be possible to get conformation from AH that this setting of "seesParty" when it shouldn't be set is indeed a bug?
Dungeon.lua:
Code: Select all
-- This file has been generated by Dungeon Editor 2.1.18
--- level 1 ---
newMap{
name = "Unnamed",
width = 32,
height = 32,
levelCoord = {0,0,0},
ambientTrack = "dungeon",
tiles = {
"beach_ground",
"beach_ground_grass",
"beach_wall",
}
}
loadLayer("tiles", {
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,1,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
})
spawn("starting_location",13,16,2,0,"starting_location_1")
spawn("beach_grass_pressure_plate",13,2,0,0,"beach_grass_pressure_plate_2")
beach_grass_pressure_plate_2.floortrigger:setTriggeredByParty(true)
beach_grass_pressure_plate_2.floortrigger:setTriggeredByMonster(false)
beach_grass_pressure_plate_2.floortrigger:setTriggeredByItem(false)
beach_grass_pressure_plate_2.floortrigger:setTriggeredByDigging(false)
beach_grass_pressure_plate_2.floortrigger:setDisableSelf(true)
beach_grass_pressure_plate_2.floortrigger:addConnector("onActivate", "brain_scr", "plate1Activated")
spawn("trickster",21,3,3,0,"trickster_1")
trickster_1.brainScript:setSource("")
spawn("script_entity",0,0,3,0,"brain_scr")
brain_scr.script:loadFile("mod_assets/scripts/brainTest.lua")
spawn("forest_heightmap",1,0,0,0,"forest_heightmap_1")
spawn("forest_day_sky",1,0,1,0,"forest_day_sky_1")
spawn("forest_ruins_wall_01",15,16,3,0,"forest_ruins_wall_01_1")
spawn("beach_grass_pressure_plate",13,17,3,0,"beach_grass_pressure_plate_1")
beach_grass_pressure_plate_1.floortrigger:setTriggeredByParty(true)
beach_grass_pressure_plate_1.floortrigger:setTriggeredByMonster(true)
beach_grass_pressure_plate_1.floortrigger:setTriggeredByItem(true)
beach_grass_pressure_plate_1.floortrigger:setTriggeredByDigging(false)
beach_grass_pressure_plate_1.floortrigger:setDisableSelf(false)
beach_grass_pressure_plate_1.floortrigger:addConnector("onActivate", "brain_scr", "plate2Activated")
spawn("forest_ruins_wall_01",14,17,1,0,"forest_ruins_wall_01_2")
spawn("forest_ruins_wall_01",14,18,1,0,"forest_ruins_wall_01_3")
spawn("forest_ruins_wall_01",15,19,3,0,"forest_ruins_wall_01_4")
spawn("forest_ruins_wall_01",14,20,1,0,"forest_ruins_wall_01_5")
spawn("forest_ruins_wall_01",15,21,3,0,"forest_ruins_wall_01_6")
spawn("forest_ruins_wall_01",15,22,3,0,"forest_ruins_wall_01_7")
spawn("forest_ruins_wall_01",14,24,1,0,"forest_ruins_wall_01_8")
spawn("forest_ruins_wall_01",14,25,1,0,"forest_ruins_wall_01_9")
spawn("forest_ruins_wall_01",14,26,1,0,"forest_ruins_wall_01_10")
spawn("forest_ruins_wall_01",15,27,3,0,"forest_ruins_wall_01_11")
spawn("forest_ruins_wall_01",15,28,3,0,"forest_ruins_wall_01_12")
spawn("forest_ruins_wall_01",15,29,3,0,"forest_ruins_wall_01_13")
spawn("forest_ruins_wall_01",15,30,3,0,"forest_ruins_wall_01_15")
spawn("trickster",20,18,3,0,"trickster_2")
trickster_2.brainScript:setSource("")
spawn("castle_door_wood",15,16,1,0,"castle_door_wood_1")
spawn("castle_door_wood",15,17,1,0,"castle_door_wood_2")
spawn("castle_door_wood",15,18,1,0,"castle_door_wood_3")
spawn("castle_door_wood",15,19,1,0,"castle_door_wood_4")
spawn("castle_door_wood",15,20,1,0,"castle_door_wood_6")
spawn("castle_door_wood",15,21,1,0,"castle_door_wood_8")
spawn("castle_door_wood",15,22,1,0,"castle_door_wood_9")
Code: Select all
monsterID1 = "trickster_1"
monsterID2 = "trickster_2"
lastSeesParty = false -- last value set by AI
brainTestObj = {
bBrainTestComplete = true,
targetSqr = {}
}
function plate1Activated()
local mob = findEntity(brain_scr.script.monsterID1)
if mob and mob.level == party.level then
brain_scr.script.initBrainTest(mob, 11, 5)
end
end
function plate2Activated()
local mob = findEntity(brain_scr.script.monsterID2)
if mob and mob.level == party.level then
brain_scr.script.initBrainTest(mob, 11, 20)
end
end
function initBrainTest(mob, x, y)
brainTestObj.targetSqr = { ["x"] = x, ["y"] = y }
brainTestObj.bBrainTestComplete = false
print("Starting brainTest")
mob.brain:addConnector("onThink", "brain_scr", "thinkTestFunc")
end
function thinkTestFunc(monster)
local br = monster.go.brain
if br.seesParty ~= lastSeesParty then
--print("new seesParty", br.seesParty, "party rel-loc: s-ahead:"..tostring(br.partyStraightAhead)..", s-behind:"..tostring(br.partyStraightBehind)..", left:"..tostring(br.partyLeft)..", right:"..tostring(br.partyRight)..", behind:"..tostring(br.partyBehind)..", ahead: "..tostring(br.partyAhead)..", adj:"..tostring(br.partryAdjacent)..", diag: "..tostring(br.partyDiagonal))
--print("onLevel: "..tostring(br.partyOnLevel)..", lastSeen: "..br.partyLastSeen..", dist:("..br.partyDistX..","..br.partyDistY.."), locXY:("..br.partyX..","..br.partyY..")")
print("Current seesParty", br.seesParty, "X,Y,facing=", br.go.x, br.go.y, br.go.facing)
lastSeesParty = br.seesParty
-- Kill brain when he first sees party
br:disable()
end
if not brainTestObj.bBrainTestComplete then
if monster.go.x == brainTestObj.targetSqr.x and monster.go.y == brainTestObj.targetSqr.y then
print("Monster found target!!! BrainTest passed.")
brainTestObj.bBrainTestComplete = true
else
br:seek(brainTestObj.targetSqr.x, brainTestObj.targetSqr.y)
end
else
-- do normal brain stuff
end
end
The level has two sections. The 1st section is used to show that seesParty works fine when walls are in between the mob and the party. My code will disable the brain as soon as the party is seen. For this test, this is at cords: 11, 6
In the 2nd section, I have both forest_ruins_wall and castle_door_wood Door objects instead of walls. Both are not sparse. You will see the mob see the party thru these doors at or near 16, 20.
Please let me know if you can re-create the issue.
UPDATE:
I decide to see if "partyLastSeen" was having issues as well. I confirm it was in a similar but actually more concerning way. Most of the time when the mob sees the party in error, it somehow is reports seeing him for 0 seconds! I am talking 0 to the nanosecond. And that makes no sense considering another turn had to have gone by. Look at my code where I keep track of when he is first seen and compare it to when he stops seeing the party. Below is a new version of my brainTest.lua. I think this is more revealing that something is not right...
Code: Select all
monsterID1 = "trickster_1"
monsterID2 = "trickster_2"
lastSeesParty = false -- last value set by AI
lastSeenTime = 0
startSeenTime = nil
brainTestObj = {
bBrainTestComplete = true,
targetSqr = {}
}
function plate1Activated()
local mob = findEntity(brain_scr.script.monsterID1)
if mob and mob.level == party.level then
brain_scr.script.initBrainTest(mob, 11, 5)
end
end
function plate2Activated()
local mob = findEntity(brain_scr.script.monsterID2)
if mob and mob.level == party.level then
--brain_scr.script.initBrainTest(mob, 11, 20)
brain_scr.script.initBrainTest(mob, 11, 28)
end
end
function initBrainTest(mob, x, y)
brainTestObj.targetSqr = { ["x"] = x, ["y"] = y }
brainTestObj.bBrainTestComplete = false
print("Starting brainTest")
mob.brain:addConnector("onThink", "brain_scr", "thinkTestFunc")
lastSeenTime = mob.brain.partyLastSeen
--print("Time vals", Time.currentTime(), Time.deltaTime, Time.systemTime())
end
function thinkTestFunc(monster)
local br = monster.go.brain
if br.partyLastSeen ~= lastSeenTime then
if not startSeenTime then
startSeenTime = br.partyLastSeen
--print("Mob did not see party for: "..tostring(br.partyLastSeen - lastSeenTime).." secs. Mob SEES party at: "..br.partyLastSeen)
end
else
if startSeenTime then
print("Mob saw party for: "..tostring(br.partyLastSeen - startSeenTime).." secs. Mob STOPED seeing party at: "..br.partyLastSeen..". Start seen time: "..startSeenTime)
startSeenTime = nil
end
end
lastSeenTime = br.partyLastSeen
--[[
if br.seesParty ~= lastSeesParty then
--print("new seesParty", br.seesParty, "party rel-loc: s-ahead:"..tostring(br.partyStraightAhead)..", s-behind:"..tostring(br.partyStraightBehind)..", left:"..tostring(br.partyLeft)..", right:"..tostring(br.partyRight)..", behind:"..tostring(br.partyBehind)..", ahead: "..tostring(br.partyAhead)..", adj:"..tostring(br.partryAdjacent)..", diag: "..tostring(br.partyDiagonal))
--print("onLevel: "..tostring(br.partyOnLevel)..", lastSeen: "..br.partyLastSeen..", dist:("..br.partyDistX..","..br.partyDistY.."), locXY:("..br.partyX..","..br.partyY..")")
print("Current seesParty", br.seesParty, "seesPartyCount", seesPartyCount, "X,Y,facing=", br.go.x, br.go.y, br.go.facing)
lastSeesParty = br.seesParty
seesPartyCount = 0
-- Kill brain when he first sees party
--br:disable()
end
seesPartyCount = seesPartyCount + 1
]]--
if not brainTestObj.bBrainTestComplete then
if monster.go.x == brainTestObj.targetSqr.x and monster.go.y == brainTestObj.targetSqr.y then
print("Monster found target!!! BrainTest passed.")
brainTestObj.bBrainTestComplete = true
else
br:seek(brainTestObj.targetSqr.x, brainTestObj.targetSqr.y)
end
else
-- do normal brain stuff
end
end
Re: Tentative changelist for 2.1.19
Update, this also happens with throwing, missiles, and wand spells. However, RunePanelComponent works fine with dual-wielding.minmay wrote:Found what I believe is a bug. Light firearms (firearms with the "light_weapon" trait) behave strangely when combined with dual-wielding: if you attack with the light firearm, it puts both hands on cooldown, but if you attack with a light melee weapon in the other hand, it doesn't put the firearm on cooldown.
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.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Re: Tentative changelist for 2.1.19
LightComponent:getFadeOut() always gives the following error when I try to call it:
Code: Select all
attempt to call a nil value
stack traceback:
[C]: in function 'error'
[string "ScriptInterface.lua"]: in function 'getFadeOut'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.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Re: Tentative changelist for 2.1.19
It would be great if you could implement these 2 methods:
champion:getPortrait() -- returns the file path to the champion portrait.
champion:setLevel(number)
Or some other way to downdgrade (or even reset) the level of the champion. champion:gainExp(negativeValue) doesn't downgrade the level.
These are needed for example for dialogs and recruiting new champions.
champion:getPortrait() -- returns the file path to the champion portrait.
champion:setLevel(number)
Or some other way to downdgrade (or even reset) the level of the champion. champion:gainExp(negativeValue) doesn't downgrade the level.
These are needed for example for dialogs and recruiting new champions.
- 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
- cloneObject viewtopic.php?f=22&t=8450
- Eleven Warrior
- Posts: 752
- Joined: Thu Apr 18, 2013 2:32 pm
- Location: Australia
Re: Tentative changelist for 2.1.19
I most certainly 2nd this motion, I do miss the:JKos wrote:It would be great if you could implement these 2 methods:
champion:getPortrait() -- returns the file path to the champion portrait.
champion:setLevel(number)
Or some other way to downdgrade (or even reset) the level of the champion. champion:gainExp(negativeValue) doesn't downgrade the level.
These are needed for example for dialogs and recruiting new champions.
champion:getPortrait() -- returns the file path to the champion portrait.
champion:setLevel(number)
With this implemented we will be able to have better starting champs for the player(s), down grade there level if they do something bad, have a player start with 4 x rattlings champs or other races etc...
Please AH can we get these codes into LOG 2?
Re: Tentative changelist for 2.1.19
Champion:getPortrait() is imposible to add in general case. Remember the portraits can be imported, so portrait data is stored in the save games. Otherwise save games couldn't be transferred between computers.
Re: Tentative changelist for 2.1.19
Meaning transfered between PC/MAC/Linux/IOS? That is pretty cool; Fallout was like that. The PC & Mac games loaded via floppy on either OS from either OS; pretty sharp feature considering the endian differences between x86 and PPC.petri wrote:Champion:getPortrait() is imposible to add in general case. Remember the portraits can be imported, so portrait data is stored in the save games. Otherwise save games couldn't be transferred between computers.
____
Is it possible to define them as materials at load? Doesn't the game fall back to the default portraits if the custom ones are not present when the save is loaded?
The only reason that users want this feature is to be able to restore the original portraits after a change; (including after changing a PC to a different one, and wanting to change it back).
**Obviously none of us know the technical impediments involved; but it would be a cool feature if it could be managed.