From a6f974da33e20970b92e812af94ac531ac66c0d8 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Mon, 2 Aug 2021 08:24:28 -0700 Subject: [PATCH] Added number-of-attacks logic for high levels of hand-to-hand etc. Added stats cross-reference to pack report. Added more smart-quote translation to packer. --- .../src/org/badvision/A2PackPartitions.groovy | 76 ++++++++++++++++++- Platform/Apple/virtual/src/plasma/combat.pla | 48 ++++++++++-- 2 files changed, 114 insertions(+), 10 deletions(-) diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy index 72b39f2b..530f9241 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy @@ -314,6 +314,10 @@ class A2PackPartitions } else if (ch == '\"') buf << "\\\"" + else if (ch == '“' || ch == '”') // translate smart quotes to straight quotes + buf << "\\\"" + else if (ch == '‘' || ch == '’') + buf << '\'' else if (prev == '^') { def cp = Character.codePointAt(ch.toUpperCase(), 0) // ^A = ctrl-A; ^M = ctrl-M (carriage return); ^Z = ctrl-Z; ^` = space @@ -2922,6 +2926,70 @@ class A2PackPartitions } } + def recordStatUse(mapName, script, statUses) + { + mapName = mapName.trim().replaceAll(/\s*-\s*[23][dD]\s*/, "") + script.block.'**'.each { blk -> + if (blk?.@type =~ /^interaction_(increase|decrease|set|get)_stat.*/) { + def statName = blk.field[0].text().trim().toLowerCase() + def getOrSet = blk.@type == "interaction_get_stat" ? "Checked" : "Set" + if (!statUses.containsKey(statName)) + statUses[statName] = [] as Set + def scriptName = script.@name + statUses[statName] << "$getOrSet on map '$mapName' in script '$scriptName'" + } + } + } + + def recordStats(data, statUses, skills) + { + def funcs = allPlayerFuncs(data.global.sheets.sheet) + funcs.each { func, index, row -> + row.attributes().sort().eachWithIndex { name, val, idx -> + if (name =~ /^skill-(.*)/) { + def skillName = name.replace("skill-", "").toLowerCase() + skills << skillName + if (!statUses.containsKey(skillName)) + statUses[skillName] = [] as Set + statUses[skillName] << "Initialized in players sheet" + } + } + } + + def el = data.global.sheets.sheet.find { it?.@name.equalsIgnoreCase("weapons") } + el.rows.row.findAll{"weapon"}.each { row -> + def kind = parseStringAttr(row, "weapon-kind").toLowerCase() + if (!statUses.containsKey(kind)) + statUses[kind] = [] as Set + statUses[kind] << "Checked by weapon-kind in combat" + } + + data.global.scripts.script.each { recordStatUse('global', it, statUses) } + data.map.each { map -> + map.scripts.script.each { recordStatUse(map.@name, it, statUses) } + } + + return [statUses, skills] + } + + def reportStatUse(data) + { + def statUses = [:] + def skills = [] as Set + + reportWriter.println( + "\n============================== Stats and Skills Cross-reference ==================================\n") + recordStats(data, statUses, skills) + statUses.keySet().sort().each { statName -> + def uses = statUses[statName] + def skillOrStat = skills.contains(statName) ? "Skill" : "Stat" + reportWriter.println "$skillOrStat '$statName':" + statUses[statName].sort().each { useStr -> + reportWriter.println " $useStr" + } + } + } + def addResourceDep(fromType, fromName, toType, toName) { assert fromType != null && fromName != null @@ -3157,6 +3225,7 @@ class A2PackPartitions reportScriptLocs(dataIn) reportFlags(dataIn) reportStoryLogs() + reportStatUse(dataIn) if (debugCompression) println "Compression savings: $compressionSavings" @@ -3793,9 +3862,11 @@ class A2PackPartitions "${parseByteAttr(row, "pack size")})") row.attributes().sort().eachWithIndex { name, val, idx -> if (name =~ /^skill-(.*)/) { + def skillName = name.replace("skill-", "") out.println(" addToList(@p=>p_skills, " + - "makeModifier(${escapeString(titleCase(name.replace("skill-", "")))}, " + + "makeModifier(${escapeString(titleCase(skillName))}, " + "${parseByteAttr(row, name)}))") + skillName = skillName.toLowerCase() } else if (name =~ /^item-/) { name = val.trim().toLowerCase() @@ -4671,7 +4742,8 @@ end } if (inst2.nWarnings > 0) { - reportWriter.println "Packing warnings:\n" + reportWriter.println( + "\n============================== Packing warnings ==================================\n") reportWriter.println inst2.warningBuf.toString() reportWriter.write() watcher.warnings(inst2.nWarnings, inst2.warningBuf.toString()) diff --git a/Platform/Apple/virtual/src/plasma/combat.pla b/Platform/Apple/virtual/src/plasma/combat.pla index 39c7a1ae..1157a6d8 100644 --- a/Platform/Apple/virtual/src/plasma/combat.pla +++ b/Platform/Apple/virtual/src/plasma/combat.pla @@ -782,10 +782,32 @@ def getWeapon(pl)#1 return first(pl=>p_items, &(p) p->t_type == TYPE_WEAPON and p->b_flags & ITEM_FLAG_EQUIP) end + +/////////////////////////////////////////////////////////////////////////////////////////////////// +def calcNumAtt(pl, isMelee, pWeapon) + byte skillPts + + skillPts = 0 + if pWeapon + if pWeapon->b_flags & WEAPON_FLAG_SINGLE_USE; return 1; fin + skillPts = scanModifiers(pl=>p_skills, pWeapon=>s_itemKind) + elsif isMelee + skillPts = scanModifiers(pl=>p_skills, @S_HAND_TO_HAND) + fin + + if skillPts >= 9 + return 3 + elsif skillPts >= 6 + return 2 + fin + return 1 +end + + /////////////////////////////////////////////////////////////////////////////////////////////////// def playerCombatTurn(pl)#1 word pWeapon, pGroup, pEnemy - byte i + byte i, j, nAttacks if !nEnemiesFighting; return 0; fin @@ -795,18 +817,28 @@ def playerCombatTurn(pl)#1 // Execute the player's choice when pl->b_combatChoice is 'M' - playerMelee(pl, pWeapon) + nAttacks = calcNumAtt(pl, TRUE, pWeapon) // TRUE=melee + displayf1("nAttacks=%d\n", nAttacks) + for i = 1 to nAttacks + playerMelee(pl, pWeapon) + if i < nAttacks; combatPause; fin + next checkSingleUse(pl, pWeapon) break is 'F' return 0 is 'S' - for i = 1 to pl->b_shotChoice - if nEnemiesFighting and pWeapon->b_clipCurrent - playerShoot(pl, pWeapon) - consumeAmmo(pl, pWeapon) - if i+1 < pl->b_shotChoice; combatPause; fin - fin + nAttacks = calcNumAtt(pl, FALSE, pWeapon) // FALSE=not melee + displayf1("nAttacks=%d\n", nAttacks) + for i = 1 to nAttacks + for j = 1 to pl->b_shotChoice + if nEnemiesFighting and pWeapon->b_clipCurrent + playerShoot(pl, pWeapon) + consumeAmmo(pl, pWeapon) + if j < pl->b_shotChoice; combatPause; fin + fin + next + if i < nAttacks; combatPause; fin next checkSingleUse(pl, pWeapon) break