Progress on group selection in combat.

This commit is contained in:
Martin Haye
2019-12-04 10:12:43 -08:00
parent 2043deeb70
commit 386494b8db

View File

@@ -44,6 +44,7 @@ byte nPartyFighting
byte nPlayersFighting byte nPlayersFighting
byte nEnemiesFighting byte nEnemiesFighting
byte isFleeing byte isFleeing
byte isAdvancing
//combatDebug// byte combatDebug //combatDebug// byte combatDebug
byte[] S_AN = "an " byte[] S_AN = "an "
@@ -58,7 +59,6 @@ word pItemUtil
const MAX_GROUPS = 3 const MAX_GROUPS = 3
byte nEnemyGroups byte nEnemyGroups
byte isAdvancing
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
def preload()#0 def preload()#0
@@ -123,12 +123,12 @@ def combatPause()#0
pause(global=>w_combatPauseCt) pause(global=>w_combatPauseCt)
// Check for speed-up / slow-down // Check for speed-up / slow-down
key = ^kbd key = ^kbd & $7F
if key == (11 + 128) or key == ('-'+128) // up-arrow or minus if key == 11 or key == '-' // up-arrow or minus
if !recordMode; ^kbdStrobe; fin ^kbdStrobe
global=>w_combatPauseCt = max(100, global=>w_combatPauseCt - addPercent(global=>w_combatPauseCt, 20)) global=>w_combatPauseCt = max(100, global=>w_combatPauseCt - addPercent(global=>w_combatPauseCt, 20))
elsif key == (10 + 128) or key == ('+'+128) // down-arrow or plus elsif key == 10 or key == '+' // down-arrow or plus
if !recordMode; ^kbdStrobe; fin ^kbdStrobe
global=>w_combatPauseCt = min(9999, global=>w_combatPauseCt + addPercent(global=>w_combatPauseCt, 20)) global=>w_combatPauseCt = min(9999, global=>w_combatPauseCt + addPercent(global=>w_combatPauseCt, 20))
fin fin
end end
@@ -380,29 +380,44 @@ def playerDodge(pPlayer)#0
// no need to display anything. Actual dodging mechanics handled in enemy attack function. // no need to display anything. Actual dodging mechanics handled in enemy attack function.
end end
///////////////////////////////////////////////////////////////////////////////////////////////////
def groupCanFight(p)#1
return first(p=>p_enemies, @canFight)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def formatGroupName(p, withDist)#1
byte count
count = sum(p=>p_enemies, NULL, @canFight)
isPlural = count <> 1
if (p=>p_enemies=>r_groupSize == 0)
if withDist
return sprintf2("%s at %d'", p=>p_enemies=>s_name, p=>p_enemies->b_enemyAttackRange)
else
return sprintf1("%s", p=>p_enemies=>s_name)
fin
fin
if withDist
return sprintf3("%d %s at %d'", count, p=>p_enemies=>s_name, p=>p_enemies->b_enemyAttackRange)
fin
return sprintf2("%d %s", count, p=>p_enemies=>s_name)
end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
def displayOpponents()#0 def displayOpponents()#0
word p word p
byte count, firstTime byte firstTime
displayStr("You face ") displayStr("You face ")
firstTime = TRUE firstTime = TRUE
p = global=>p_enemyGroups p = global=>p_enemyGroups
while p while p
if !firstTime if groupCanFight(p)
if p=>p_nextObj if !firstTime
displayStr(", ") displayStr(p=>p_nextObj ?? ", " :: " and ")
else
displayStr(" and ")
fin fin
fin firstTime = FALSE
firstTime = FALSE displayStr(formatGroupName(p, TRUE))
count = sum(p=>p_enemies, NULL, @canFight)
isPlural = count <> 1
if (p=>p_enemies=>r_groupSize == 0)
displayf2("%s at %d'", p=>p_enemies=>s_name, p=>p_enemies->b_enemyAttackRange)
else
displayf3("%d %s at %d'", count, p=>p_enemies=>s_name, p=>p_enemies->b_enemyAttackRange)
fin fin
p = p=>p_nextObj p = p=>p_nextObj
loop loop
@@ -414,7 +429,7 @@ def displayOption(key, str)#0
rawDisplayStr("\n (") rawDisplayStr("\n (")
displayChar(key) displayChar(key)
rawDisplayStr(")^T028") rawDisplayStr(")^T028")
rawDisplayStr(str) displayStr(str)
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -425,7 +440,7 @@ def minEnemyDist()#1
// Process each group // Process each group
p = global=>p_enemyGroups p = global=>p_enemyGroups
while p while p
if first(p=>p_enemies, @canFight) if groupCanFight(p)
minDist = min(minDist, p=>p_enemies->b_enemyAttackRange) minDist = min(minDist, p=>p_enemies->b_enemyAttackRange)
fin fin
p = p=>p_nextObj p = p=>p_nextObj
@@ -433,6 +448,71 @@ def minEnemyDist()#1
return minDist return minDist
end end
///////////////////////////////////////////////////////////////////////////////////////////////////
def noneInRange()#1
rawDisplayStr("^D") // clear to end of page
displayStr("No enemy in range.")
combatPause
return FALSE
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Phase 0: count alive & in-range gangs
// Phase 1: display gangs
// Phase 2: select gang by number, return enemyNum
def groupLoop(minDist, phase, choiceNum)#1
word p
byte n
p = global=>p_enemyGroups
n = 0
while p
if p=>p_enemies->b_enemyAttackRange <= minDist and groupCanFight(p)
if phase == 1
displayOption(n + 'A', formatGroupName(p, FALSE))
elsif phase == 2 and n == choiceNum
return p->b_enemyNum
fin
n++
fin
p = p=>p_nextObj
loop
return n
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def chooseGroup(pl, minDist)#1
word p
byte nAvailGroups, choiceNum
// First, determine how many groups are alive and within striking distance
nAvailGroups = groupLoop(minDist, 0, 0)
// If nobody in range, ack!
if !nAvailGroups; return noneInRange(); fin
// If only one group, the choice is trivially obvious.
if nAvailGroups == 1
choiceNum = 0
else
rawDisplayf1("^D%s attack:", pl=>s_name) // ctrl-D = clear to end of page
groupLoop(minDist, 1, 0)
while TRUE
choiceNum = getUpperKey()
if choiceNum == $1B // esc
return FALSE
fin
choiceNum = choiceNum - 'A'
if choiceNum >= 0 and choiceNum < nAvailGroups; break; fin
beep()
loop
fin
// Success.
pl->b_gangChoice = groupLoop(minDist, 2, choiceNum)
return TRUE
end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// Determine number of shots. Only gets called for projectile attack // Determine number of shots. Only gets called for projectile attack
def chooseShotNumber(pl, pWeapon)#0 def chooseShotNumber(pl, pWeapon)#0
@@ -452,7 +532,7 @@ def chooseShotNumber(pl, pWeapon)#0
if nChoices <= 1; return; fin if nChoices <= 1; return; fin
// Let player choose // Let player choose
rawDisplayf1("^D%s shoot:", pl=>s_name) // ctrl-D = clear to end of page rawDisplayf1("^D%s shot type:", pl=>s_name) // ctrl-D = clear to end of page
if pWeapon->ba_attacks[0]; displayOption('O', "One shot"); fin if pWeapon->ba_attacks[0]; displayOption('O', "One shot"); fin
if pWeapon->ba_attacks[1] == 2 if pWeapon->ba_attacks[1] == 2
displayOption('D', "Double-shot") displayOption('D', "Double-shot")
@@ -530,7 +610,7 @@ end
def playerCombatChoose(pl)#0 def playerCombatChoose(pl)#0
word p, pWeapon word p, pWeapon
byte key byte key
byte canShoot, canReload, canChange, canAdvance byte canShoot, canReload, canChange, canAdvance, redisplayMenu
word cursX, cursY word cursX, cursY
// The party advances all at once // The party advances all at once
@@ -560,41 +640,53 @@ def playerCombatChoose(pl)#0
p = p=>p_nextObj p = p=>p_nextObj
loop loop
// Let them know their options redisplayMenu = TRUE
setCursor(cursX, cursY)
rawDisplayStr("^D") // clear to end of page
displayf1("%s:\nM)elee, ", pl=>s_name)
if pWeapon
// Special (for e.g. bows): clipSize zero means weapon reloads automatically
if pWeapon=>r_projectileDmg and !pWeapon->b_clipCurrent and !pWeapon->b_clipSize
pItemUtil=>itemutil_reloadWeapon(pl, pWeapon, FALSE) // silently reload
fin
if pWeapon->b_clipCurrent
canShoot = TRUE
if pWeapon->b_clipSize
displayf2("S)hoot %d:%d, ", pWeapon->b_clipCurrent, pWeapon->b_clipSize))
else
displayStr("S)hoot, ")
fin
fin
if pWeapon->b_clipCurrent < pWeapon->b_clipSize
canReload = TRUE
displayStr("R)eload, ")
fin
fin
if canChange
displayStr("C)hange weapon, ")
fin
displayStr("D)odge, ")
canAdvance = (pl == global=>p_players) and (minEnemyDist() > 5) // only one advance per turn
if canAdvance; displayStr("A)dvance, "); fin
displayStr("F)lee")
setCursor(cursX, cursY)
// Loop until a valid option is chosen
while TRUE while TRUE
// Let them know their options
if redisplayMenu
setCursor(cursX, cursY)
rawDisplayStr("^D") // clear to end of page
displayf1("%s:\nM)elee, ", pl=>s_name)
if pWeapon
// Special (for e.g. bows): clipSize zero means weapon reloads automatically
if pWeapon=>r_projectileDmg and !pWeapon->b_clipCurrent and !pWeapon->b_clipSize
pItemUtil=>itemutil_reloadWeapon(pl, pWeapon, FALSE) // silently reload
fin
if pWeapon->b_clipCurrent
canShoot = TRUE
if pWeapon->b_clipSize
displayf2("S)hoot %d:%d, ", pWeapon->b_clipCurrent, pWeapon->b_clipSize))
else
displayStr("S)hoot, ")
fin
fin
if pWeapon->b_clipCurrent < pWeapon->b_clipSize
canReload = TRUE
displayStr("R)eload, ")
fin
fin
if canChange
displayStr("C)hange weapon, ")
fin
displayStr("D)odge, ")
canAdvance = (pl == global=>p_players) and (minEnemyDist() > 5) // only one advance per turn
if canAdvance; displayStr("A)dvance, "); fin
displayStr("F)lee")
setCursor(cursX, cursY)
fin
pl->b_combatChoice = getUpperKey() pl->b_combatChoice = getUpperKey()
redisplayMenu = FALSE
when pl->b_combatChoice when pl->b_combatChoice
is 'M' is 'M'
if !chooseGroup(pl, 5)
redisplayMenu = TRUE
break
fin
setCursor(cursX, cursY)
return return
is 'F' is 'F'
isFleeing = TRUE isFleeing = TRUE
@@ -603,6 +695,11 @@ def playerCombatChoose(pl)#0
return return
is 'S' is 'S'
if canShoot if canShoot
if !chooseGroup(pl, pWeapon->b_weaponRange)
redisplayMenu = TRUE
break
fin
setCursor(cursX, cursY)
chooseShotNumber(pl, pWeapon) chooseShotNumber(pl, pWeapon)
setCursor(cursX, cursY) setCursor(cursX, cursY)
return return
@@ -638,7 +735,7 @@ def playerCombatChoose(pl)#0
fin fin
return return
wend wend
beep() if !redisplayMenu; beep(); fin
loop loop
end end