Combat order determination implemented.

This commit is contained in:
Martin Haye 2015-11-29 09:21:03 -08:00
parent 4eafd97388
commit da7356450c
2 changed files with 144 additions and 9 deletions

View File

@ -116,6 +116,10 @@ byte decimalBuf[7]
byte tabBuf[5]
byte isPlural
// Combat variables that don't need to be saved in game state
byte nPlayersFighting
byte nEnemiesFighting
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions used by assembly code
asm __defs
@ -1532,7 +1536,96 @@ include "playtype.pla"
//include "heaptest.pla"
///////////////////////////////////////////////////////////////////////////////////////////////////
def combat()
def playerCanFight(p)
return p=>w_health > 0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def enemyCanFight(p)
return p=>w_health > 0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def playerCombatTurn(pl)
displayf1("Player turn: %s\n", pl=>s_name)
getUpperKey()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def enemyCombatTurn(pe)
displayf1("Enemy turn: %s\n", pe=>s_name)
getUpperKey()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def combatInsert(toAdd)
word p, pPrev
// Find the proper position based on combat order number (keep largest first in the list)
pPrev = global + p_combatFirst
while TRUE
p = *pPrev
if !p or p->b_combatOrder < toAdd->b_combatOrder
break
fin
pPrev = p + p_combatNext
loop
// Add it right there.
toAdd=>p_combatNext = *pPrev
*pPrev = toAdd
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def determineCombatOrder()
word p, p2
nPlayersFighting = 0
nEnemiesFighting = 0
// Do each player character, with random chance based on their agility
global=>p_combatFirst = NULL
p = global=>p_players
while p
if playerCanFight(p)
p->b_combatOrder = rand16() % (p->b_agility * 10)
combatInsert(p)
nPlayersFighting = nPlayersFighting + 1
fin
p = p=>p_nextObj
loop
// Then all the enemies, with random chance based on their chance to hit.
p = global=>p_enemyGroups
while p
p2 = p=>p_enemies
while p2
if enemyCanFight(p2)
p2->b_combatOrder = rand16() % p2->b_chanceToHit
combatInsert(p2)
nEnemiesFighting = nEnemiesFighting + 1
fin
p2 = p2=>p_nextObj
loop
p = p=>p_nextObj
loop
// For debuggging, print out the order
printf2("nPlayersFighting=%d nEnemiesFighting=%d.\nCombat order:\n", nPlayersFighting, nEnemiesFighting)
p = global=>p_combatFirst
while p
printf2(" %s (n=%d)\n", p=>s_name, p->b_combatOrder)
p = p=>p_combatNext
loop
// FIXME: for debugging only
^$C051
getUpperKey()
^$C050
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def startCombat()
word p, p2, n, s
// Create the enemy group(s).
@ -1542,9 +1635,14 @@ def combat()
// Display portrait of first group
setPortrait(global=>p_enemyGroups=>p_enemies=>ba_images[0])
// Say who we're fighting
// We're going to do all our text drawing in window 2. Also, might as well
// set everything up so that the map gets redrawn when combat finishes.
setWindow2()
clearWindow()
textDrawn = TRUE
needRender = TRUE
// Say who we're fighting
when rand16() % 5
is 0
s = "Uh oh, it's gunna' be one of THOSE days.\n"; break
@ -1584,19 +1682,50 @@ def combat()
if n == 'F'
clearWindow()
displayStr("Fight!")
break
return TRUE
elsif n == 'R'
clearWindow()
displayStr("Coward.")
textDrawn = TRUE
needRender = TRUE
break
return FALSE
fin
beep()
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def doCombat()
word p
// Show portrait and threat details, find out if player wants to fight (vs. run)
if !startCombat(); return; fin
// Do each round of combat until player wins or loses.
while TRUE
determineCombatOrder()
p = global=>p_combatFirst
while p
clearWindow()
if !nPlayersFighting
displayStr("You lost.")
return
elsif !nEnemiesFighting
displayStr("You won!")
return
fin
when p->t_type
is TYPE_PLAYER
playerCombatTurn(p); break
is TYPE_ENEMY
enemyCombatTurn(p); break
otherwise
brk()
wend
p = p=>p_combatNext
loop
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set up the command table for 3D mode
def initCmds()
@ -1611,7 +1740,7 @@ def initCmds()
initCmd('T', @kbdTeleport)
initCmd('P', @showPos)
initCmd('/', @testPortrait)
initCmd('!', @combat)
initCmd('!', @doCombat)
// Commands handled differently in 3D vs 2D
if mapIs3D

View File

@ -6,6 +6,7 @@ struc Global
byte t_type
word p_players
word p_enemyGroups
word p_combatFirst
end
byte typeTbl_Global[] = Global, p_players, p_enemyGroups, 0
@ -14,6 +15,9 @@ struc Player
byte t_type
word p_nextObj
word s_name
byte b_combatOrder
word p_combatNext
word w_health
// Innate attributes
byte b_intelligence
@ -33,7 +37,6 @@ struc Player
byte b_wilderness
// Status
word w_health
word w_maxHealth
// Lists
@ -142,8 +145,11 @@ struc Enemy
byte t_type
word p_nextObj
word s_name
byte ba_images[2]
byte b_combatOrder
word p_combatNext
word w_health
byte ba_images[2]
byte b_hitBonus
byte b_attackType // 1=melee, 2=projectile
word s_attackText