From 58d3386dffb002c8fb31ec179963bf553d2b2054 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Wed, 24 May 2017 07:47:47 -0700 Subject: [PATCH] Reformatted inventory and stats screen. --- Platform/Apple/virtual/src/plasma/gamelib.plh | 6 + .../Apple/virtual/src/plasma/gameloop.pla | 124 ++++++++++-------- Platform/Apple/virtual/src/plasma/party.pla | 124 +++++++++--------- 3 files changed, 140 insertions(+), 114 deletions(-) diff --git a/Platform/Apple/virtual/src/plasma/gamelib.plh b/Platform/Apple/virtual/src/plasma/gamelib.plh index 42b7abc5..379840d5 100644 --- a/Platform/Apple/virtual/src/plasma/gamelib.plh +++ b/Platform/Apple/virtual/src/plasma/gamelib.plh @@ -10,6 +10,9 @@ import gamelib + /////////// Shared numeric constants ////////////// + const OVERSIZE_WINDOW_HEIGHT = 174 + //////////// Shared library routines //////////// // Let's try to keep these predef's in lexical order predef addEncounterZone @@ -118,6 +121,9 @@ import gamelib predef setWindow3 predef showMapName predef showParty + predef sprintf1 + predef sprintf2 + predef sprintf3 predef streqi predef strncpy predef takeItemFromPlayer diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index 654ade0d..76181b64 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -377,6 +377,8 @@ export asm addToString rts end +// Complete string building (including plural processing), and return pointer +// to the string (in the input buffer) export asm finishString !zone { +asmPlasm 1 @@ -458,7 +460,7 @@ export asm finishString .done dey sty inbuf ; save new length - lda #inbuf rts } @@ -942,18 +944,6 @@ end /////////////////////////////////////////////////////////////////////////////////////////////////// // General methods -export def strncpy(dst, src, maxlen) - byte i, l - - l = ^src - if l > maxlen; l = maxlen; fin - ^dst = l - for i = 1 to l - dst->[i] = src->[i] - next - return l -end - /////////////////////////////////////////////////////////////////////////////////////////////////// // Fatal error: print message and stop the system. export def fatal(msg) @@ -990,6 +980,43 @@ def abs(n) fin end +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Convert a lower-case character to upper-case (or return unchanged if it's not lower-case) +export def charToUpper(c) + if c >= 'a' and c <= 'z' + return c - $20 + fin + return c +end + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Compare two strings for equality, ignoring case. +export def streqi(a, b) + word limit, leneq + leneq = ^a == ^b + limit = a + min(^a, ^b) + a++; b++ + while a <= limit + if charToUpper(^a) <> charToUpper(^b); return FALSE; fin + a++; b++ + loop + return leneq +end + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Copy part of a string +export def strncpy(dst, src, maxlen) + byte i, l + + l = ^src + if l > maxlen; l = maxlen; fin + ^dst = l + for i = 1 to l + dst->[i] = src->[i] + next + return l +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Read a string from the keyboard using the font manager, and intern it to the heap. export def getStringResponse() @@ -1085,15 +1112,20 @@ end export def displayf1(str, arg1); displayf3(str, arg1, 0, 0); end export def displayf2(str, arg1, arg2); displayf3(str, arg1, arg2, 0); end -// Like printf, but displays text using font engine -export def rawDisplayf3(str, arg1, arg2, arg3) +// Like printf, but buffers string in $200 +export def sprintf3(str, arg1, arg2, arg3) buildString(@addToString) printf3(str, arg1, arg2, arg3) - rawDisplayStr(finishString(isPlural)) + return finishString(isPlural) end -export def rawDisplayf1(str, arg1); rawDisplayf3(str, arg1, 0, 0); end -export def rawDisplayf2(str, arg1, arg2); rawDisplayf3(str, arg1, arg2, 0); end +export def sprintf1(str, arg1); return sprintf3(str, arg1, 0, 0); end +export def sprintf2(str, arg1, arg2); return sprintf3(str, arg1, arg2, 0); end + +// Like printf, but displays text using font engine +export def rawDisplayf1(str, arg1); rawDisplayStr(sprintf3(str, arg1, 0, 0)); end +export def rawDisplayf2(str, arg1, arg2); rawDisplayStr(sprintf3(str, arg1, arg2, 0)); end +export def rawDisplayf3(str, arg1, arg2, arg3); rawDisplayStr(sprintf3(str, arg1, arg2, arg3)); end /////////////////////////////////////////////////////////////////////////////////////////////////// export def parseDec(str) @@ -1128,15 +1160,6 @@ export def parseDecWithDefault(str, default) return parseDec(str) end -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Convert a lower-case character to upper-case (or return unchanged if it's not lower-case) -export def charToUpper(c) - if c >= 'a' and c <= 'z' - return c - $20 - fin - return c -end - /////////////////////////////////////////////////////////////////////////////////////////////////// // Get a keystroke and convert it to upper case export def getUpperKey() @@ -1338,23 +1361,32 @@ end // Window that covers the entire inner area (destroys frame image, so be sure to loadMainFrame // afterwards) export def setOversizeWindow() - hline(getScreenLine(5)+1, 0, 0, 36, 0) - hline(getScreenLine(6)+1, $F8, $FF, 36, $8F) - hline(getScreenLine(7)+1, $FC, $FF, 36, $9F) - hline(getScreenLine(8)+1, $8C, 0, 36, $98) - vline(getScreenLine(9)+1, $8C, 174) - vline(getScreenLine(9)+38, $98, 174) - hline(getScreenLine(182)+1, $8C, 0, 36, $98) - hline(getScreenLine(183)+1, $FC, $FF, 36, $9F) - hline(getScreenLine(184)+1, $F8, $FF, 36, $8F) - hline(getScreenLine(185)+1, 0, 0, 36, 0) + // Draw border (if not already drawn) + if frameLoaded + hline(getScreenLine(5)+1, 0, 0, 36, 0) + hline(getScreenLine(6)+1, $F8, $FF, 36, $8F) + hline(getScreenLine(7)+1, $FC, $FF, 36, $9F) + hline(getScreenLine(8)+1, $8C, 0, 36, $98) + vline(getScreenLine(9)+1, $8C, 174) + vline(getScreenLine(9)+38, $98, 174) + hline(getScreenLine(182)+1, $8C, 0, 36, $98) + hline(getScreenLine(183)+1, $FC, $FF, 36, $9F) + hline(getScreenLine(184)+1, $F8, $FF, 36, $8F) + hline(getScreenLine(185)+1, 0, 0, 36, 0) + frameLoaded = 0 // since we just destroyed it + fin setWindow(9, 183, 14, 267) // Top, Bottom, Left, Right - frameLoaded = 0 // since we destroyed it end /////////////////////////////////////////////////////////////////////////////////////////////////// export def rightJustifyStr(str, rightX) - rawDisplayf2("^T%D%s", rightX - calcWidth(str), str) + word space + space = rightX - calcWidth(str) + if (space > 0) + rawDisplayStr("^T") // do not use printf variants, since it might overwrite str + rawDisplayStr(convert3Dec(space)) + fin + rawDisplayStr(str) end /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2187,20 +2219,6 @@ export def clearEncounterZones() global=>p_encounterZones = NULL end -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Compare two strings for equality, ignoring case. -export def streqi(a, b) - word limit, leneq - leneq = ^a == ^b - limit = a + min(^a, ^b) - a++; b++ - while a <= limit - if charToUpper(^a) <> charToUpper(^b); return FALSE; fin - a++; b++ - loop - return leneq -end - /////////////////////////////////////////////////////////////////////////////////////////////////// // Called by user-defined map scripts to initiate a combat encounter. export def scriptCombat(mapCode) diff --git a/Platform/Apple/virtual/src/plasma/party.pla b/Platform/Apple/virtual/src/plasma/party.pla index 5ba5e2a0..8eaecffc 100644 --- a/Platform/Apple/virtual/src/plasma/party.pla +++ b/Platform/Apple/virtual/src/plasma/party.pla @@ -31,9 +31,10 @@ const TYPE_USE = $0102 const TYPE_DROP = $0103 // Tab positions -const CHAR_WND_STAT_X = 30 -const CHAR_WND_STATLBL_X = 38 -const CHAR_WND_INV_X = 18 +const CHAR_WND_INVLBL_X = 10 +const CHAR_WND_INV_X = 25 +const CHAR_WND_STAT_X = 174 +const CHAR_WND_STATLBL_X = 182 const STATS_COL_1 = 45 const STATS_COL_2 = 140 @@ -104,28 +105,29 @@ def unequip(player, type, kind) loop end +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Display title of a column at top but below character name. Optionally append a second string, +// then leave a little vertical space below before beginning the content of the column. +def showColumnTitle(x, title, page, nPages) + rawDisplayf2("^V000\n^J^J^L^J^T%D%s", x, title) + if nPages > 1 + rawDisplayf2(" - p.%d/%d", page, nPages) + fin + rawDisplayStr("^N\n^J^J") +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Display inventory pane def showInventory(player, page, rows, select) word item - byte s_item, n_item, n_page, first + byte s_item, n_item, n_page, totalPages, first s_item = 0 n_item = 0 n_page = page * rows item = player=>p_items - setMapWindow() - clearWindow() - rawDisplayStr("^Y^LInventory^N") - if !select - if page - rawDisplayf1("^T008<%d", page) - fin - if countList(item) > n_page + rows - rawDisplayf1("^T108%d>", page+2) - fin - fin - rawDisplayStr("^V012") // leave half-a-line of space + totalPages = (countList(item)+rows-1) / rows + showColumnTitle(CHAR_WND_INV_X-10, "Inventory", page+1, totalPages) if page while item and n_item < n_page item = item=>p_nextObj @@ -136,24 +138,21 @@ def showInventory(player, page, rows, select) while item and n_item < (n_page + rows) if !first; displayChar('\n'); fin first = FALSE - if itemMatch(item, select) - displayf1("%c)", 'A' + s_item) - s_item++ - fin - rawDisplayf1("^T%D", CHAR_WND_INV_X) - _displayItemName(item) + if item->t_type == TYPE_WEAPON or item->t_type == TYPE_ARMOR if item->b_flags & ITEM_FLAG_EQUIP - displayStr(" *") + rawDisplayStr("*") fin fin + + rawDisplayf2("^T%D%c.", CHAR_WND_INVLBL_X, 'A' + s_item) + s_item++ + + rawDisplayf1("^T%D", CHAR_WND_INV_X) + _displayItemName(item) n_item++ item = item=>p_nextObj loop - while n_item < (n_page + rows) - displayChar('\n') - n_item++ - loop return s_item end @@ -183,21 +182,29 @@ def numToPlayer(num) end def displayDice(dice) - if (dice & $0F) - rawDisplayf3("%dd%d+%d", (dice >> 12) & $0F, (dice >> 8) & $0F, dice & $0F) + byte n, d, p + n = (dice >> 12) & $0F + d = (dice >> 8) & $0F + p = dice & $FF + if (p) + rightJustifyStr(sprintf3("%dd%d+%d", n, d, p), CHAR_WND_STAT_X) else - rawDisplayf2("^T010%dd%d", (dice >> 12) & $0F, (dice >> 8) & $0F) + rightJustifyStr(sprintf2("%dd%d", n, d), CHAR_WND_STAT_X) fin end +def vspace() + rawDisplayStr("^J^J^J^J") +end + // Show stats in the right panel def showStats(player) word weapon, dmg - setWindow2() - clearWindow() - rawDisplayStr("^Y^LStats^N^V012") + showColumnTitle(CHAR_WND_STAT_X, "Stats", 0, 0) rightJustifyNum(player=>w_health, CHAR_WND_STAT_X); rawDisplayf1("^T%DHealth\n", CHAR_WND_STATLBL_X) + rightJustifyNum(player=>w_maxHealth, CHAR_WND_STAT_X); rawDisplayf1("^T%DMax health\n", CHAR_WND_STATLBL_X) + vspace() rightJustifyNum(player->b_intelligence, CHAR_WND_STAT_X); rawDisplayf1("^T%DIntelligence\n", CHAR_WND_STATLBL_X) rightJustifyNum(player->b_strength, CHAR_WND_STAT_X); rawDisplayf1("^T%DStrength\n", CHAR_WND_STATLBL_X) rightJustifyNum(player->b_agility, CHAR_WND_STAT_X); rawDisplayf1("^T%DAgility\n", CHAR_WND_STATLBL_X) @@ -205,6 +212,7 @@ def showStats(player) rightJustifyNum(player->b_charisma, CHAR_WND_STAT_X); rawDisplayf1("^T%DCharisma\n", CHAR_WND_STATLBL_X) rightJustifyNum(player->b_spirit, CHAR_WND_STAT_X); rawDisplayf1("^T%DSpirit\n", CHAR_WND_STATLBL_X) rightJustifyNum(player->b_luck, CHAR_WND_STAT_X); rawDisplayf1("^T%DLuck\n", CHAR_WND_STATLBL_X) + vspace() rightJustifyNum(player->b_armor, CHAR_WND_STAT_X); rawDisplayf1("^T%DArmor\n", CHAR_WND_STATLBL_X) // Get weapon weapon = player=>p_items @@ -212,24 +220,22 @@ def showStats(player) if weapon->t_type == TYPE_WEAPON and weapon->b_flags & ITEM_FLAG_EQUIP; break; fin weapon = weapon=>p_nextObj loop - if weapon - dmg = weapon=>r_projectileDmg - else - dmg = 0 - fin - if dmg > 0 - displayDice(dmg) + + if weapon and weapon=>r_projectileDmg + displayDice(weapon=>r_projectileDmg) rawDisplayf1("^T%DProjectile\n", CHAR_WND_STATLBL_X) - else - if weapon - dmg = weapon=>r_meleeDmg - else - dmg = $01400 - fin - displayDice(dmg) - rawDisplayf1("^T%DMelee\n", CHAR_WND_STATLBL_X) fin - //rightJustifyNum(global=>w_gold, CHAR_WND_STAT_X); rawDisplayf1("^T%DGold (party)", CHAR_WND_STATLBL_X) + + if weapon + dmg = weapon=>r_meleeDmg + else + dmg = $01400 + fin + displayDice(dmg) + rawDisplayf1("^T%DMelee\n", CHAR_WND_STATLBL_X) + + vspace() + rightJustifyNum(global=>w_gold, CHAR_WND_STAT_X); rawDisplayf1("^T%DGold (party)", CHAR_WND_STATLBL_X) end // Show aquired skills in lower right panel @@ -237,8 +243,6 @@ def showSkills(player) word skill byte col - setWindow3() - clearWindow() rawDisplayStr("^T040^LSkills^L") displaySkill("Aim", player->b_aiming, 0) displaySkill("Fists", player->b_handToHand, 1) @@ -253,8 +257,8 @@ def showSkills(player) end // Show player data -def showMenu(vMap) - rawDisplayf1("^V%D^T012E)quip, U)se, D)rop", vMap - 9) +def showMenu() + rawDisplayf1("^V%D^T012E)quip, U)se, D)rop", OVERSIZE_WINDOW_HEIGHT - 9 - 1) end // Select an item and equip/unequip it. Returns TRUE if anything changed. @@ -283,8 +287,6 @@ def doUse(player, i_page, i_rows) rawDisplayStr("\n^T032Which item?") item = itemNum(player, i_rows * i_page, getUpperKey() - 'A', TYPE_USE) if item - setWindow2() - clearWindow() if item=>p_modifiers and streqi(item=>p_modifiers=>s_name, "health") if player=>w_health < player=>w_maxHealth player=>w_health = min(player=>w_health + item=>p_modifiers=>w_modValue, player=>w_maxHealth) @@ -343,28 +345,28 @@ end // the item is returned; else NULL is returned. def _doPlayerSheet(num) word player, item - word hMap, vMap, i_rows + word i_rows byte i_page, redisplay setOversizeWindow() clearWindow() // Get size of inventory pane in chars - getMapWindow(@hMap, @vMap) - i_rows = (vMap / 9) - 3 // 9 rows per line; minus 3 lines for header/footer + i_rows = (OVERSIZE_WINDOW_HEIGHT / 9) - 4 // 9 rows per line; minus 4 lines for header/footer i_page = 0 redisplay = TRUE repeat player = numToPlayer(num) if !player; return; fin // Invalid player if redisplay - // First, display the player's name in the title bar - showMapName(player=>s_name) + // First, display the player's name at the top + clearWindow() + rawDisplayf1("^Y^I %s ^N\n", player=>s_name) showStats(player) redisplay = FALSE fin showInventory(player, i_page, i_rows, 0) - showMenu(vMap) + showMenu() // Get a key, do something when getUpperKey() // Select another player to show