diff --git a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy index 6698c1d5..b8cec7d8 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy @@ -108,6 +108,42 @@ class PackPartitions ++nWarnings } + def escapeString(inStr) + { + def buf = new StringBuilder() + buf << '\"' + def prev = '\0' + def count = 0 + def stop = false + inStr.eachWithIndex { ch, idx -> + if (!stop) { + if (count >= 255) { + printWarning("String must be 254 characters or less. Everything after the following will be discarded: '${inStr[0..idx]}'") + stop = true + } + else if (ch == '^') { + if (prev == '^') + buf << ch + } + else if (ch == '\"') { + buf << "\\\"" + ++count // account for extra backslash + } + else if (prev == '^') { + def cp = Character.codePointAt(ch.toUpperCase(), 0) + if (cp > 64 && cp < 96) + buf << "\\\$" << String.format("%02X", cp - 64) + } + else + buf << ch + ++count + prev = ch + } + } + buf << '\"' + return buf.toString() + } + def parseMap(map, tiles) { // Parse each row of the map @@ -1698,9 +1734,9 @@ class PackPartitions if (image2.size() > 0 && !portraitNames.contains(humanNameToSymbol(image2, false))) throw new Exception("Image '$image2' not found") - def hitPoints = row.@"hit-points" + def hitPoints = row.@"hit-points"; assert hitPoints - def attackType = row.@"attack-type" + def attackType = row.@"attack-type"; assert attackType def attackTypeCode = attackType.toLowerCase() == "melee" ? 1 : attackType.toLowerCase() == "projectile" ? 2 : 0 @@ -1781,25 +1817,84 @@ class PackPartitions } replaceIfDiff("build/src/plasma/gen_enemies.pla") } - } - def genWeapon(out, row) + def parseStringAttr(row, attrName) { - out.println " //weapon name=${row.@name}" + def val = row."@$attrName" + assert val != null : "Missing column '$attrName'" + return val.trim() } - def genArmor(out, row) + def parseByteAttr(row, attrName) + { + def val = parseStringAttr(row, attrName) + if (!val) return 0 + val = val.replace("'", "") // Change 5' to just 5, e.g. for weapon range + assert val ==~ /^\d*$/ : "\"$attrName\" should be numeric" + val = val.toInteger() + assert val >= 0 && val <= 255 : "\"$attrName\" must be 0..255" + return val + } + + def parseWordAttr(row, attrName) + { + def val = parseStringAttr(row, attrName) + if (!val) return 0 + assert val ==~ /^\d*$/ : "\"$attrName\" should be numeric" + val = val.toInteger() + assert val >= -32768 && val <= 32767 : "\"$attrName\" must be -32768..32767" + return val + } + + def parseModifier(row, attr1, attr2) + { + def bonusValue = parseWordAttr(row, attr1) + def bonusName = parseStringAttr(row, attr2) + if (!bonusValue || !bonusName) return "NULL" + return "makeModifier(${escapeString(bonusName)}, $bonusValue)" + } + + def parseDiceAttr(row, attrName) + { + def val = parseStringAttr(row, attrName) + if (!val) return 0 + return parseDice(val) + } + + def genWeapon(func, row, out) + { + def name = parseStringAttr(row, "name") + withContext(name) + { + out.println(" return makeWeapon_pt2(makeWeapon_pt1(" + + "${escapeString(name)}, " + + "${escapeString(parseStringAttr(row, "weapon-kind"))}, " + + "${parseWordAttr(row, "price")}, " + + "${parseModifier(row, "bonus-value", "bonus-attribute")}, " + + "${escapeString(parseStringAttr(row, "ammo-kind"))}, " + + "${parseByteAttr(row, "clip-size")}, " + + "${parseDiceAttr(row, "melee-damage")}, " + + "${parseDiceAttr(row, "projectile-damage")}), " + + "${parseByteAttr(row, "single-shot")}, " + + "${parseByteAttr(row, "semi-auto-shots")}, " + + "${parseByteAttr(row, "auto-shots")}, " + + "${parseByteAttr(row, "range")}, " + + "${escapeString(parseStringAttr(row, "combat-text"))})") + } + } + + def genArmor(func, row, out) { out.println " //armor name=${row.@name}" } - def genAmmo(out, row) + def genAmmo(func, row, out) { out.println " //ammo name=${row.@name}" } - def genItem(out, row) + def genItem(func, row, out) { out.println " //item name=${row.@name}" } @@ -1835,7 +1930,7 @@ class PackPartitions out.println(" fin") } out.println(" puts(code)") - out.println(" fatal(\"No code match\")") + out.println(" fatal(\"$funcName\")") out.println("end\n") } @@ -1904,10 +1999,10 @@ class PackPartitions { out.println("def _$func()") switch (typeName) { - case "weapon": genWeapon(out, row); break - case "armor": genArmor(out, row); break - case "ammo": genAmmo(out, row); break - case "item": genItem(out, row); break + case "weapon": genWeapon(func, row, out); break + case "armor": genArmor(func, row, out); break + case "ammo": genAmmo(func, row, out); break + case "item": genItem(func, row, out); break default: assert false } out.println("end\n") @@ -2147,40 +2242,6 @@ class PackPartitions def indent = 0 def variables = [] as Set - def emitString(inStr) - { - out << '\"' - def prev = '\0' - def count = 0 - def stop = false - inStr.eachWithIndex { ch, idx -> - if (!stop) { - if (count >= 255) { - printWarning("String must be 254 characters or less. Everything after the following will be discarded: '${inStr[0..idx]}'") - stop = true - } - else if (ch == '^') { - if (prev == '^') - out << ch - } - else if (ch == '\"') { - out << "\\\"" - ++count // account for extra backslash - } - else if (prev == '^') { - def cp = Character.codePointAt(ch.toUpperCase(), 0) - if (cp > 64 && cp < 96) - out << "\\\$" << String.format("%02X", cp - 64) - } - else - out << ch - ++count - prev = ch - } - } - out << '\"' - } - def getScriptName(script) { if (script.block.size() == 0) @@ -2412,8 +2473,7 @@ class PackPartitions chunks.eachWithIndex { chunk, idx -> outIndented((idx == chunks.size()-1 && blk.@type == 'text_println') ? \ 'scriptDisplayStrNL(' : 'scriptDisplayStr(') - emitString(chunk) - out << ")\n" + out << escapeString(chunk) << ")\n" // Workaround for strings filling up the frame stack outIndented("tossStrings()\n") } @@ -2495,7 +2555,7 @@ class PackPartitions packVarGet(blk) break case 'text': - emitString(getSingle(blk.field, 'TEXT').text()) + out << escapeString(getSingle(blk.field, 'TEXT').text()) break default: assert false : "Expression type '${blk.@type}' not yet implemented." @@ -2593,9 +2653,7 @@ class PackPartitions def maxDist = blk.field[3].text().toInteger() def chance = (int)(blk.field[4].text().toFloat() * 10.0) assert chance > 0 && chance <= 1000 - outIndented("addEncounterZone(") - emitString(code) - out << ", $x, $y, $maxDist, $chance)\n" + outIndented("addEncounterZone(${escapeString(code)}, $x, $y, $maxDist, $chance)\n") } def packTeleport(blk) diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index be832de4..0fbf8b84 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -2155,22 +2155,23 @@ def _makeModifier(name, value) end /////////////////////////////////////////////////////////////////////////////////////////////////// -def _makeArmor(name, kind, cost, armorValue, modifier) +def _makeArmor(name, kind, price, armorValue, modifier) word p; p = mmgr(HEAP_ALLOC, TYPE_ARMOR) p=>s_name = mmgr(HEAP_INTERN, name) p=>s_itemKind = mmgr(HEAP_INTERN, kind) - p=>w_cost = cost + p=>w_price = price p->b_armorValue = armorValue p=>p_modifiers = modifier return p end /////////////////////////////////////////////////////////////////////////////////////////////////// -def _makeWeapon_pt1(name, kind, cost, ammoKind, clipSize, meleeDmg, projectileDmg) +def _makeWeapon_pt1(name, kind, price, modifier, ammoKind, clipSize, meleeDmg, projectileDmg) word p; p = mmgr(HEAP_ALLOC, TYPE_WEAPON) p=>s_name = mmgr(HEAP_INTERN, name) p=>s_itemKind = mmgr(HEAP_INTERN, kind) - p=>w_cost = cost + p=>w_price = price + p=>p_modifiers = modifier p=>s_ammoKind = mmgr(HEAP_INTERN, ammoKind) p->b_clipSize = clipSize p->b_clipCurrent = clipSize @@ -2180,7 +2181,7 @@ def _makeWeapon_pt1(name, kind, cost, ammoKind, clipSize, meleeDmg, projectileDm end /////////////////////////////////////////////////////////////////////////////////////////////////// -def _makeWeapon_pt2(p, modifier, attack0, attack1, attack2, weaponRange, combatText) +def _makeWeapon_pt2(p, attack0, attack1, attack2, weaponRange, combatText) p->ba_attacks[0] = attack0 p->ba_attacks[1] = attack1 p->ba_attacks[2] = attack2 diff --git a/Platform/Apple/virtual/src/plasma/globalScripts.pla b/Platform/Apple/virtual/src/plasma/globalScripts.pla index 0a12a266..8af7b0d8 100644 --- a/Platform/Apple/virtual/src/plasma/globalScripts.pla +++ b/Platform/Apple/virtual/src/plasma/globalScripts.pla @@ -26,7 +26,7 @@ def new_Armor_Chaps p = mmgr(HEAP_ALLOC, TYPE_ARMOR) p=>s_name = mmgr(HEAP_INTERN, "Chaps") p=>s_itemKind = mmgr(HEAP_INTERN, "pants") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p->b_armorValue = 2 return p @@ -38,7 +38,7 @@ def new_Armor_ShamanHeaddress() p = mmgr(HEAP_ALLOC, TYPE_ARMOR) p=>s_name = mmgr(HEAP_INTERN, "Shaman Headdress(es)") p=>s_itemKind = mmgr(HEAP_INTERN, "hat(s)") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p->b_armorValue = 2 return p @@ -50,7 +50,7 @@ def new_Armor_TahnkuPants() p = mmgr(HEAP_ALLOC, TYPE_ARMOR) p=>s_name = mmgr(HEAP_INTERN, "Tahnku Pants") p=>s_itemKind = mmgr(HEAP_INTERN, "pants") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p->b_armorValue = 2 return p @@ -62,7 +62,7 @@ def new_Armor_TahnkuVest() p = mmgr(HEAP_ALLOC, TYPE_ARMOR) p=>s_name = mmgr(HEAP_INTERN, "Tahnku Vest(s)") p=>s_itemKind = mmgr(HEAP_INTERN, "shirt(s)") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p->b_armorValue = 2 return p @@ -74,7 +74,7 @@ def new_Weapon_Handgun p = mmgr(HEAP_ALLOC, TYPE_WEAPON) p=>s_name = mmgr(HEAP_INTERN, "Handgun") p=>s_itemKind = mmgr(HEAP_INTERN, "handgun(s)") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p=>s_ammoKind = mmgr(HEAP_INTERN, "Bullet(s)") p->b_clipSize = 6 @@ -93,7 +93,7 @@ def new_Weapon_SpiritBow p = mmgr(HEAP_ALLOC, TYPE_WEAPON) p=>s_name = mmgr(HEAP_INTERN, "Spirit Bow") p=>s_itemKind = mmgr(HEAP_INTERN, "bow(s)") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p=>s_ammoKind = mmgr(HEAP_INTERN, "Arrow(s)") p->b_clipSize = 12 @@ -113,7 +113,7 @@ def new_Weapon_SpiritBlade p = mmgr(HEAP_ALLOC, TYPE_WEAPON) p=>s_name = mmgr(HEAP_INTERN, "Spirit Blade") p=>s_itemKind = mmgr(HEAP_INTERN, "blade(s)") - p=>w_cost = -99 // for now + p=>w_price = -99 // for now // no modifiers, max uses, etc. for now p=>s_ammoKind = NULL p->b_clipSize = 0 diff --git a/Platform/Apple/virtual/src/plasma/playtype.plh b/Platform/Apple/virtual/src/plasma/playtype.plh index d0f3cefc..87313cbb 100644 --- a/Platform/Apple/virtual/src/plasma/playtype.plh +++ b/Platform/Apple/virtual/src/plasma/playtype.plh @@ -90,7 +90,7 @@ struc Item word p_nextObj word s_name word s_itemKind - word w_cost + word w_price word p_modifiers // list:modifier end @@ -104,7 +104,7 @@ struc Weapon word p_nextObj word s_name word s_itemKind - word w_cost + word w_price word p_modifiers // list:modifier // Usables properties byte b_maxUses @@ -128,7 +128,7 @@ struc Armor word p_nextObj word s_name word s_itemKind - word w_cost + word w_price word p_modifiers // list:modifier // Usables properties byte b_maxUses @@ -145,7 +145,7 @@ struc Stuff word p_nextObj word s_name word s_itemKind - word w_cost + word w_price // Stuff properties word w_count word w_maxCount