mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-06-26 00:29:30 +00:00
Added support for arbitrary game flags, and most of stat increase/decrease.
This commit is contained in:
parent
2eff48233f
commit
df446bc38b
|
@ -96,8 +96,12 @@
|
|||
<block type="interaction_give_item"></block>
|
||||
<block type="interaction_take_item"></block>
|
||||
<block type="interaction_has_item"></block>
|
||||
<block type="interaction_get_stat"></block>
|
||||
<block type="interaction_increase_stat"></block>
|
||||
<block type="interaction_decrease_stat"></block>
|
||||
<block type="interaction_get_flag"></block>
|
||||
<block type="interaction_set_flag"></block>
|
||||
<block type="interaction_clr_flag"></block>
|
||||
</category>
|
||||
<category id="customTypes" name="Custom Types">
|
||||
</category>
|
||||
|
|
|
@ -580,7 +580,7 @@ if (typeof Mythos === "undefined") {
|
|||
Blockly.Blocks['text_getboolean'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(54);
|
||||
this.setColour(Blockly.Blocks.logic.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField("Get Yes or No");
|
||||
this.setOutput(true, "Boolean");
|
||||
|
@ -618,12 +618,24 @@ if (typeof Mythos === "undefined") {
|
|||
Blockly.Blocks['interaction_has_item'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(54);
|
||||
this.setColour(Blockly.Blocks.logic.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField("player has item")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME");
|
||||
this.setOutput(true, "Boolean");
|
||||
this.setTooltip('');
|
||||
this.setTooltip('Check if player has a given item');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['interaction_get_stat'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField("player's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("stat");
|
||||
this.setOutput(true, "Number");
|
||||
this.setTooltip('Get player stat');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['interaction_increase_stat'] = {
|
||||
|
@ -633,10 +645,10 @@ if (typeof Mythos === "undefined") {
|
|||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.appendDummyInput()
|
||||
.appendField("Increase player stat")
|
||||
.appendField("Increase player's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("by")
|
||||
.appendField(new Blockly.FieldTextInput("0"), "AMOUNT")
|
||||
.appendField("stat by")
|
||||
.appendField(new Blockly.FieldTextInput("0"), "AMOUNT");
|
||||
this.setOutput(false);
|
||||
this.setTooltip('Increase stat of player');
|
||||
}
|
||||
|
@ -648,14 +660,54 @@ if (typeof Mythos === "undefined") {
|
|||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.appendDummyInput()
|
||||
.appendField("Decrease player stat")
|
||||
.appendField("Decrease player's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("by")
|
||||
.appendField(new Blockly.FieldTextInput("0"), "AMOUNT")
|
||||
.appendField("stat by")
|
||||
.appendField(new Blockly.FieldTextInput("0"), "AMOUNT");
|
||||
this.setOutput(false);
|
||||
this.setTooltip('Decrease stat of player');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['interaction_get_flag'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(Blockly.Blocks.logic.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField("game's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("flag is set");
|
||||
this.setOutput(true, "Boolean");
|
||||
this.setTooltip('Get game flag');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['interaction_set_flag'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(54);
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.appendDummyInput()
|
||||
.appendField("Set game's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("flag");
|
||||
this.setOutput(false);
|
||||
this.setTooltip('Set a game flag');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['interaction_clr_flag'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
this.setColour(54);
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.appendDummyInput()
|
||||
.appendField("Clear game's")
|
||||
.appendField(new Blockly.FieldTextInput(""), "NAME")
|
||||
.appendField("flag");
|
||||
this.setOutput(false);
|
||||
this.setTooltip('Clear a game flag');
|
||||
}
|
||||
};
|
||||
Blockly.Blocks['graphics_set_portrait'] = {
|
||||
init: function () {
|
||||
this.setHelpUrl(Mythos.helpUrl);
|
||||
|
|
|
@ -2811,6 +2811,9 @@ end
|
|||
case 'interaction_increase_stat':
|
||||
case 'interaction_decrease_stat':
|
||||
packChangeStat(blk); break
|
||||
case 'interaction_set_flag':
|
||||
case 'interaction_clr_flag':
|
||||
packChangeFlag(blk); break
|
||||
default:
|
||||
printWarning "don't know how to pack block of type '${blk.@type}'"
|
||||
}
|
||||
|
@ -2886,7 +2889,53 @@ end
|
|||
assert itemFunc : "Can't locate item '$name'"
|
||||
outIndented("takeItemFromPlayer(${escapeString(name)})\n")
|
||||
}
|
||||
|
||||
|
||||
def nameToStat(name) {
|
||||
switch (name.toLowerCase().trim()) {
|
||||
case "intelligence": return "@S_INTELLIGENCE"; return
|
||||
case "strength": return "@S_STRENGTH"; return
|
||||
case "agility": return "@S_AGILITY"; return
|
||||
case "stamina": return "@S_STAMINA"; return
|
||||
case "spirit": return "@S_SPIRIT"; return
|
||||
case "luck": return "@S_LUCK"; return
|
||||
case "health": return "@S_HEALTH"; return
|
||||
case "max health": return "@S_MAX_HEALTH"; return
|
||||
case "aiming": return "@S_AIMING"; return
|
||||
case "hand to hand": return "@S_HAND_TO_HAND"; return
|
||||
case "dodging": return "@S_DODGING"; return
|
||||
case "gold": return "@S_GOLD"; return
|
||||
default: assert false : "Unrecognized stat '$name'"
|
||||
}
|
||||
}
|
||||
|
||||
def packChangeStat(blk)
|
||||
{
|
||||
def name = getSingle(blk.value, 'NAME').text()
|
||||
def amount = getSingle(blk.value, 'AMOUNT').text().toInteger()
|
||||
assert amount > 0 && amount < 32767
|
||||
def stat = nameToStat(name)
|
||||
outIndented("setStat(getStat($stat) ${blk.@type == 'interaction_increase_stat' ? '+' : '-'} $amount)\n")
|
||||
}
|
||||
|
||||
def packGetStat(blk)
|
||||
{
|
||||
def name = getSingle(blk.field, 'NAME').text()
|
||||
def stat = nameToStat(name)
|
||||
out << "getStat($stat)"
|
||||
}
|
||||
|
||||
def packGetFlag(blk)
|
||||
{
|
||||
def name = getSingle(blk.field, 'NAME').text()
|
||||
out << "getGameFlag(${escapeString(name)})"
|
||||
}
|
||||
|
||||
def packChangeFlag(blk)
|
||||
{
|
||||
def name = getSingle(blk.field, 'NAME').text()
|
||||
outIndented("setGameFlag(${escapeString(name)}, ${blk.@type == 'interaction_set_flag' ? 1 : 0})\n")
|
||||
}
|
||||
|
||||
def isStringExpr(blk)
|
||||
{
|
||||
return blk.@type == "text_getstring" || blk.@type == "text"
|
||||
|
@ -2953,6 +3002,12 @@ end
|
|||
case 'interaction_has_item':
|
||||
packHasItem(blk)
|
||||
break
|
||||
case 'interaction_get_stat':
|
||||
packGetStat(blk)
|
||||
break
|
||||
case 'interaction_get_flag':
|
||||
packGetFlag(blk)
|
||||
break
|
||||
default:
|
||||
assert false : "Expression type '${blk.@type}' not yet implemented."
|
||||
}
|
||||
|
|
|
@ -23,10 +23,16 @@ import gamelib
|
|||
predef addEncounterZone, showMapName, setMapWindow, makeModifier
|
||||
predef addGold, countGold, payGold
|
||||
predef calcPlayerArmor, diskActivity, rdkey, initHeap, scriptCombat
|
||||
predef giveItemToPlayer, takeItemFromPlayer, playerHasItem, changePlayerStat
|
||||
predef giveItemToPlayer, takeItemFromPlayer, playerHasItem, getStat, setStat
|
||||
predef setGameFlag, getGameFlag
|
||||
|
||||
// Shared string constants
|
||||
|
||||
// First: attributes
|
||||
byte[] S_INTELLIGENCE, S_STRENGTH, S_AGILITY, S_STAMINA, S_CHARISMA, S_SPIRIT, S_LUCK
|
||||
byte[] S_HEALTH, S_AIMING, S_HAND_TO_HAND, S_DODGING, S_GOLD
|
||||
byte[] S_HEALTH, S_MAX_HEALTH, S_AIMING, S_HAND_TO_HAND, S_DODGING, S_GOLD
|
||||
|
||||
// Next: common events
|
||||
byte[] S_ENTER, S_USE
|
||||
|
||||
end
|
||||
|
|
|
@ -107,10 +107,13 @@ export byte[] S_CHARISMA = "charisma"
|
|||
export byte[] S_SPIRIT = "spirit"
|
||||
export byte[] S_LUCK = "luck"
|
||||
export byte[] S_HEALTH = "health"
|
||||
export byte[] S_MAX_HEALTH = "max health"
|
||||
export byte[] S_AIMING = "aiming"
|
||||
export byte[] S_HAND_TO_HAND = "hand-to-hand"
|
||||
export byte[] S_HAND_TO_HAND = "hand to hand"
|
||||
export byte[] S_DODGING = "dodging"
|
||||
export byte[] S_GOLD = "gold"
|
||||
export byte[] S_ENTER = "enter"
|
||||
export byte[] S_USE = "use"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions used by assembly code
|
||||
|
@ -2227,6 +2230,15 @@ export def payGold(amount)
|
|||
return amount
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def scanForNamedObj(p_obj, name)
|
||||
while p_obj
|
||||
if streqi(p_obj=>s_name, name); return p_obj; fin
|
||||
p_obj = p_obj=>p_nextObj
|
||||
loop
|
||||
return NULL
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def giveItemToPlayer(itemFunc)
|
||||
word p_module, funcTbl, func, p_item
|
||||
|
@ -2241,28 +2253,21 @@ export def giveItemToPlayer(itemFunc)
|
|||
func = *(funcTbl + itemFunc)
|
||||
p_item = func()
|
||||
|
||||
// Add the item to the player's inventory, and free up the item module
|
||||
addToList(@global=>p_players=>p_items, p_item)
|
||||
// Avoid giving duplicate items.
|
||||
if !scanForNamedObj(global=>p_players=>p_items, p_item=>s_name)
|
||||
addToList(@global=>p_players=>p_items, p_item)
|
||||
fin
|
||||
|
||||
// Finished with the item module now.
|
||||
mmgr(FREE_MEMORY, p_module)
|
||||
end
|
||||
|
||||
def scanForItem(itemName)
|
||||
word p_player
|
||||
word p_item
|
||||
p_player = global=>p_players // default to first player
|
||||
p_item = p_player=>p_items
|
||||
while p_item
|
||||
if streqi(p_item=>s_name, itemName); return p_item; fin
|
||||
p_item = p_item=>p_nextObj
|
||||
loop
|
||||
return FALSE
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def takeItemFromPlayer(itemName)
|
||||
word p_player
|
||||
word p_item
|
||||
p_player = global=>p_players // default to first player
|
||||
p_item = scanForItem(itemName)
|
||||
p_item = scanForNamedObj(p_player=>p_items, itemName)
|
||||
if p_item
|
||||
removeFromList(@p_player=>p_items, p_item)
|
||||
else
|
||||
|
@ -2270,19 +2275,64 @@ export def takeItemFromPlayer(itemName)
|
|||
fin
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def playerHasItem(itemName)
|
||||
return scanForItem(itemName) <> NULL
|
||||
return scanForNamedObj(itemName) <> NULL
|
||||
end
|
||||
|
||||
export def changePlayerStat(statName, add)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def getStat(statName)
|
||||
word player
|
||||
player = global=>p_players // default to first player
|
||||
when statName
|
||||
is @S_STRENGTH
|
||||
global=>p_players->b_strength = max(0, min(255, global=>p_players->b_strength + add))
|
||||
is @S_STRENGTH; return player->b_strength
|
||||
otherwise
|
||||
puts(statName); fatal("Unknown attr to incr/decr")
|
||||
puts(statName); fatal("Unknown stat")
|
||||
wend
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def clampByte(val)
|
||||
return max(0, min(255, val))
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def setStat(statName, val)
|
||||
word player
|
||||
player = global=>p_players // default to first player
|
||||
when statName
|
||||
is @S_STRENGTH; player->b_strength = clampByte(val)
|
||||
otherwise
|
||||
puts(statName); fatal("Unknown stat")
|
||||
wend
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def setGameFlag(flagName, val)
|
||||
word p_flag
|
||||
p_flag = scanForNamedObj(global=>p_gameFlags, flagName)
|
||||
if p_flag
|
||||
if val == 0 // setting flag to zero removes it
|
||||
removeFromList(@global=>p_gameFlags, p_flag)
|
||||
else
|
||||
p_flag=>w_modValue = val
|
||||
fin
|
||||
elsif val <> 0
|
||||
addToList(@global=>p_gameFlags, makeModifier(flagName, val))
|
||||
fin
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
export def getGameFlag(flagName)
|
||||
word p_flag
|
||||
p_flag = scanForNamedObj(global=>p_gameFlags, flagName)
|
||||
if p_flag
|
||||
return p_flag=>w_modValue
|
||||
else
|
||||
return 0
|
||||
fin
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def startGame()
|
||||
word p_module
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Garbage collection pointer offsets within each type
|
||||
byte typeTbl_Global[] = Global, p_players, p_enemyGroups, p_combatFirst, p_encounterZones, 0
|
||||
byte typeTbl_Global[] = Global, p_players, p_enemyGroups, p_combatFirst, p_encounterZones, p_gameFlags, 0
|
||||
byte typeTbl_Player[] = Player, p_nextObj, s_name, p_combatNext, p_skills, p_items, p_effects, 0
|
||||
byte typeTbl_Modifier[] = Modifier, p_nextObj, s_name, 0
|
||||
byte typeTbl_Effect[] = Effect, p_nextObj, s_name, 0
|
||||
|
|
|
@ -32,6 +32,9 @@ struc Global
|
|||
|
||||
// Heap size for restoring saved game
|
||||
word w_heapSize
|
||||
|
||||
// General flags maintained by scripts. Linked list of Modifiers.
|
||||
word p_gameFlags
|
||||
end
|
||||
|
||||
const PLAYER_FLAG_NPC = $01
|
||||
|
|
Loading…
Reference in New Issue
Block a user