mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-02-21 12:29:05 +00:00
Fixed memory management problems in combat (preloaded funcs, item generation). Fixed problems with join/split. Normalized keyboard commands on inv screen. Fixed using TNT if Paul has it instead of plyr.
This commit is contained in:
parent
1e00b8f703
commit
b723a25bef
@ -1691,7 +1691,7 @@ class A2PackPartitions
|
||||
assert spaceUsed == partFile.length()
|
||||
}
|
||||
|
||||
println "Game version: V $gameVersion"
|
||||
println "Game version: V$gameVersion"
|
||||
}
|
||||
|
||||
def writePartition(stream, partNum, chunks)
|
||||
|
@ -1473,10 +1473,12 @@ reset: !zone
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
outOfMemErr: !zone
|
||||
!if DEBUG = 0 { jsr printMem } ; always print, even in non-debug mode
|
||||
jsr inlineFatal : !text "OutOfMem", 0
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
reservedErr: !zone
|
||||
!if DEBUG = 0 { jsr printMem } ; always print, even in non-debug mode
|
||||
jsr inlineFatal : !text "DblAlloc", 0
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
@ -30,6 +30,29 @@ byte[] S_AN = "an "
|
||||
byte[] S_A = "a "
|
||||
byte[] S_EMPTY = ""
|
||||
|
||||
// To save time, we preload global funcs
|
||||
const NUM_PRELOADS = 4
|
||||
byte[] toPreload = GS_COMBAT_INTRO, GS_COMBAT_PROMPT, GS_ENEMY_INTRO, GS_COMBAT_WIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def preload()#0
|
||||
byte i
|
||||
for i = 0 to NUM_PRELOADS-1
|
||||
mmgr(QUEUE_LOAD, toPreload[i]<<8 | RES_TYPE_MODULE)
|
||||
next
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def freePreloaded()#0
|
||||
byte i
|
||||
word p
|
||||
for i = 0 to NUM_PRELOADS-1
|
||||
p = mmgr(QUEUE_LOAD, toPreload[i]<<8 | RES_TYPE_MODULE) // only way to get ptr back
|
||||
mmgr(FREE_MEMORY, p)
|
||||
next
|
||||
mmgr(FINISH_LOAD, 0)
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def combatPause()#0
|
||||
byte key
|
||||
@ -895,6 +918,7 @@ def collectLootAndXP()#2
|
||||
displayf2("%s%s! ", anOrA(pItem=>s_name), pItem=>s_name)
|
||||
fin
|
||||
fin
|
||||
mmgr(FREE_MEMORY, pItemsModule)
|
||||
lootedItem = TRUE
|
||||
fin
|
||||
fin
|
||||
@ -910,9 +934,7 @@ def startCombat(mapCode)#1
|
||||
word p, p2, n, s
|
||||
|
||||
// Pre-load some global funcs
|
||||
mmgr(QUEUE_LOAD, GS_COMBAT_INTRO<<8 | RES_TYPE_MODULE)
|
||||
mmgr(QUEUE_LOAD, GS_COMBAT_PROMPT<<8 | RES_TYPE_MODULE)
|
||||
mmgr(QUEUE_LOAD, GS_ENEMY_INTRO<<8 | RES_TYPE_MODULE)
|
||||
preload()
|
||||
|
||||
// Setup
|
||||
isFleeing = FALSE
|
||||
@ -1053,10 +1075,12 @@ def _combat_zoneEncounter(s_encZone)#1
|
||||
p = global=>p_combatFirst
|
||||
while TRUE // not just "while p", so that we always check nPlayersFighting etc.
|
||||
if !nPlayersFighting
|
||||
freePreloaded()
|
||||
return -99 // special code for death
|
||||
elsif !nEnemiesFighting
|
||||
processWin()
|
||||
// Note: no need to clear heap -- the caller does that.
|
||||
freePreloaded()
|
||||
return 1
|
||||
elsif !p
|
||||
break
|
||||
@ -1068,6 +1092,7 @@ def _combat_zoneEncounter(s_encZone)#1
|
||||
if isFleeing
|
||||
displayStr("\nYou have fled.")
|
||||
// Note: no need to clear heap -- the caller does that.
|
||||
freePreloaded()
|
||||
return 0
|
||||
fin
|
||||
if p->b_combatChoice <> 'D'
|
||||
|
@ -69,6 +69,7 @@ export byte mapIs3D = 0
|
||||
word mapNameHash = 0
|
||||
word totalMapWidth
|
||||
word totalMapHeight
|
||||
word pCurMap
|
||||
|
||||
byte needRender = FALSE
|
||||
byte needShowParty = FALSE
|
||||
@ -1369,11 +1370,11 @@ def printVersion()#0
|
||||
^$25 = 22
|
||||
crout()
|
||||
^$24 = 25
|
||||
puts("V ")
|
||||
puts("V")
|
||||
setWindow(183, 192, 161, 261)
|
||||
clearWindow()
|
||||
setWindow(183, 192, 168, 252)
|
||||
rawDisplayStr("^YV ")
|
||||
rawDisplayStr("^YV")
|
||||
p = pResourceIndex
|
||||
len = readAuxByte(p)
|
||||
while len
|
||||
@ -1451,7 +1452,7 @@ end
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Window for the mid-size lower right bar
|
||||
export def setWindow3()#0
|
||||
setWindow(144, 180, 154, 267) // Top, Bottom, Left, Right
|
||||
setWindow(144, 181, 154, 267) // Top, Bottom, Left, Right
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1672,8 +1673,6 @@ end
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load code and data, set up everything to display a 2D or 3D map
|
||||
def initMap(x, y, dir)#0
|
||||
word pMap
|
||||
|
||||
// Reset memory (our module will stay since memory manager locked it upon load)
|
||||
mmgr(RESET_MEMORY, 0)
|
||||
|
||||
@ -1701,7 +1700,7 @@ def initMap(x, y, dir)#0
|
||||
// Load the map
|
||||
curMapPartition = lookupResourcePart(mapIs3D+1, mapNum)
|
||||
mmgr(START_LOAD, curMapPartition)
|
||||
pMap = mmgr(QUEUE_LOAD, mapNum<<8 | (RES_TYPE_2D_MAP+mapIs3D))
|
||||
pCurMap = mmgr(QUEUE_LOAD, mapNum<<8 | (RES_TYPE_2D_MAP+mapIs3D))
|
||||
pGlobalTileset = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_TILESET) // even in 3d, need tiles for compass/clock/etc.
|
||||
mmgr(FINISH_LOAD, 0)
|
||||
|
||||
@ -1719,7 +1718,7 @@ def initMap(x, y, dir)#0
|
||||
// init the script module, if any, which will end up calling us back at the setScriptInfo
|
||||
triggerTbl = NULL
|
||||
setWindow2()
|
||||
initDisplay(curMapPartition, mapNum, pMap, x, y, dir)
|
||||
initDisplay(curMapPartition, mapNum, pCurMap, x, y, dir)
|
||||
texturesLoaded = TRUE
|
||||
needRender = FALSE
|
||||
textDrawn = FALSE
|
||||
@ -2380,11 +2379,11 @@ def showPlayerSheet(num)#1
|
||||
textDrawn = FALSE
|
||||
scriptEvent(@S_USE, pItemToUse=>s_name)
|
||||
if !textDrawn
|
||||
displayStr("\nNothing happened.")
|
||||
textDrawn = TRUE
|
||||
else
|
||||
textDrawn = oldFlg
|
||||
scriptDisplayStr("Nothing happened.")
|
||||
textClearCountdown = 3
|
||||
if mapIs3D and texturesLoaded; copyWindow(); fin
|
||||
fin
|
||||
textDrawn = oldFlg
|
||||
fin
|
||||
return 0
|
||||
end
|
||||
@ -2514,6 +2513,14 @@ end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def loadGame()#1
|
||||
// Since old map may have been modified by scripts, force it to really be gone.
|
||||
if pCurMap
|
||||
mmgr(FREE_MEMORY, pCurMap)
|
||||
mmgr(SET_MEM_TARGET, pCurMap)
|
||||
mmgr(REQUEST_MEMORY, 5)
|
||||
mmgr(FREE_MEMORY, pCurMap)
|
||||
pCurMap = NULL
|
||||
fin
|
||||
loadEngine(MOD_DISKOPS)=>diskops_loadGame()
|
||||
restoreMapPos()
|
||||
return 0
|
||||
@ -2907,7 +2914,7 @@ export def addPlayerToParty(playerFuncNum)#0
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def removeNamed(name, pList)#0
|
||||
def removeNamed(name, pList)#1
|
||||
word p_thing
|
||||
p_thing = scanForNamedObj(*pList, name)
|
||||
if p_thing
|
||||
@ -2917,14 +2924,22 @@ export def removeNamed(name, pList)#0
|
||||
else
|
||||
removeFromList(pList, p_thing)
|
||||
fin
|
||||
else
|
||||
printf1("Warning: couldn't find '%s' to remove.\n", name)
|
||||
return TRUE
|
||||
fin
|
||||
return FALSE
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def takeItemFromPlayer(p_player, itemName)#0
|
||||
removeNamed(itemName, @p_player=>p_items) // default to first player
|
||||
// First, try the script-specified player
|
||||
if removeNamed(itemName, @p_player=>p_items); return; fin
|
||||
|
||||
// Fall back to all players, e.g. Prosp. Paul using his TNT.
|
||||
p_player = global=>p_players
|
||||
while p_player
|
||||
if removeNamed(itemName, @p_player=>p_items); return; fin
|
||||
p_player = p_player=>p_nextObj
|
||||
loop
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -165,9 +165,8 @@ def showDerived(player)#0
|
||||
|
||||
rawDisplayf2("^T%DLevel %d\n", STAT_X-5, player->b_level)
|
||||
if player->b_skillPoints
|
||||
vspace()
|
||||
rawDisplayf2("^T%D%s\n", STAT_X-5, "LEVEL UP!")
|
||||
vspace()
|
||||
rawDisplayf2("\n^T%D%s\n", STAT_X-5, "^I LEVEL UP ^N")
|
||||
rawDisplayf2("^T%D%s\n", STAT_X-5+8, "in S)kills\n")
|
||||
fin
|
||||
rightJustifyNum(player=>w_curXP, STAT_X)
|
||||
rawDisplayf2("^T%D%s\n", STATLBL_X, "Current XP")
|
||||
@ -338,13 +337,7 @@ def showInvMenu(player, totalItems, itemPage, itemsOnPage)#0
|
||||
|
||||
if playerCount > 1; rawDisplayf1("Plyr [1-%d], ", playerCount); fin
|
||||
|
||||
if player->b_skillPoints > 0
|
||||
rawDisplayStr("^ILvl U)p^N, ")
|
||||
else
|
||||
rawDisplayStr("S)kills, ")
|
||||
fin
|
||||
|
||||
rawDisplayStr("[Esc]")
|
||||
rawDisplayStr("S)kills, [Esc]")
|
||||
end
|
||||
|
||||
// Display menu for selecting inventory items
|
||||
@ -375,11 +368,8 @@ def showItemMenu(item)#0
|
||||
clearMenuRect()
|
||||
type = item->t_type
|
||||
if type == TYPE_ARMOR or type == TYPE_WEAPON
|
||||
if isEquipped(item)
|
||||
rawDisplayStr("U)nequip, ")
|
||||
else
|
||||
rawDisplayStr("E)quip, ")
|
||||
fin
|
||||
if isEquipped(item); rawDisplayStr("un-"); fin
|
||||
rawDisplayStr("E)quip, ")
|
||||
elsif type == TYPE_PLAIN_ITEM or type == TYPE_FANCY_ITEM
|
||||
rawDisplayStr("U)se, ")
|
||||
if isSplittable(item); rawDisplayStr("S)plit, "); fin
|
||||
@ -489,7 +479,7 @@ def doSplit(player, item)#1
|
||||
rawDisplayf1("Split off 1-%d: ", item=>w_count - 1)
|
||||
nToSplit = parseDec(getStringResponse())
|
||||
fin
|
||||
if nToSplit
|
||||
if nToSplit >= 1 and nToSplit <= item=>w_count-1
|
||||
item=>w_count = item=>w_count - nToSplit
|
||||
newItem = mmgr(HEAP_ALLOC, TYPE_FANCY_ITEM)
|
||||
memcpy(item, newItem, FancyItem)
|
||||
@ -498,7 +488,6 @@ def doSplit(player, item)#1
|
||||
item=>p_nextObj = newItem
|
||||
return 1
|
||||
fin
|
||||
beep
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -522,13 +511,9 @@ def doJoin(player, item)#1
|
||||
pPrev = @match=>p_nextObj
|
||||
match = *pPrev
|
||||
loop
|
||||
if anyJoined
|
||||
displayDone()
|
||||
return 1
|
||||
fin
|
||||
if anyJoined; return 1; fin
|
||||
clearMenuRect()
|
||||
rawDisplayStr("No joinable stack found.")
|
||||
beep
|
||||
pause(800)
|
||||
return 0
|
||||
end
|
||||
@ -611,17 +596,14 @@ def interactWithItem(player, item)#1
|
||||
ok = TRUE
|
||||
displayItems(item, matchEquipped(player, item))
|
||||
while TRUE
|
||||
if ok
|
||||
showItemMenu(item)
|
||||
else
|
||||
beep
|
||||
fin
|
||||
showItemMenu(item)
|
||||
if !ok; beep; fin
|
||||
ok = FALSE
|
||||
sel = getUpperKey()
|
||||
when sel
|
||||
// Equip player with weapon/armor
|
||||
is 'E'
|
||||
if (item->t_type == TYPE_ARMOR or item->t_type == TYPE_WEAPON) and !isEquipped(item)
|
||||
if (item->t_type == TYPE_ARMOR or item->t_type == TYPE_WEAPON)
|
||||
doEquip(player, item)
|
||||
return displayDone()
|
||||
fin
|
||||
@ -630,10 +612,6 @@ def interactWithItem(player, item)#1
|
||||
is 'U'
|
||||
if item->t_type == TYPE_PLAIN_ITEM or item->t_type == TYPE_FANCY_ITEM
|
||||
return doUse(player, item) // general 'use' handled by outer engine, because it might involve graphics
|
||||
elsif (item->t_type == TYPE_ARMOR or item->t_type == TYPE_WEAPON) and isEquipped(item)
|
||||
doEquip(player, item)
|
||||
displayItems(item, matchEquipped(player, item))
|
||||
ok = TRUE
|
||||
fin
|
||||
break
|
||||
// Trade an item
|
||||
@ -645,17 +623,15 @@ def interactWithItem(player, item)#1
|
||||
// Split a stack
|
||||
is 'S'
|
||||
if isSplittable(item)
|
||||
if doSplit(player, item)
|
||||
return NULL
|
||||
fin
|
||||
ok = doSplit(player, item)
|
||||
if ok; displayItems(item, matchEquipped(player, item)); fin
|
||||
fin
|
||||
break
|
||||
// Join stacks
|
||||
is 'J'
|
||||
if isJoinable(item)
|
||||
if doJoin(player, item)
|
||||
return NULL
|
||||
fin
|
||||
ok = doJoin(player, item)
|
||||
if ok; displayItems(item, matchEquipped(player, item)); fin
|
||||
fin
|
||||
break
|
||||
// Destroy an item
|
||||
@ -797,7 +773,7 @@ def _showPlayerSheet(player_num)#1 // funcTbl functions always have to return a
|
||||
if sel == 'X' and mode <> 'I' // switch from stats to inv
|
||||
mode = 'I'
|
||||
redisplay = 2
|
||||
elsif (sel == 'S' or sel == 'U') and mode <> 'S' // switch from inv to stats
|
||||
elsif sel == 'S' and mode <> 'S' // switch from inv to stats
|
||||
mode = 'S'
|
||||
redisplay = 2
|
||||
elsif mode == 'I'
|
||||
|
Loading…
x
Reference in New Issue
Block a user