I've published a new script in the Game Creators store, to turn a GameGuru game into a 3D version of a classic JRPG adventure, with multiple player characters and a turn-based battle system. More about that in the store forum:
https://www.tgcstore.net/forum/thread/164
I try to keep the store product as solid as possible, so I'll post all the unofficial content, modifications, tests, etc. to this thread. I have also decided to publish the core of RPG2 logic for free, so if you just want to use the experience point/level up system, but don't want to pay for my Menu, Shop and Battle system, feel free to use the rpg2_global_essentials. Hopefully you'll find it useful. You will also need it if you want to test my free scripts without buying the actual script set.
rpg2_global_essentials.lua
If you want to test the scripts without buying the actual script set (or build something that utilises my RPG2 tables), you can use this set of global functions to load the essential parts of the RPG Module 2. This script has the core functions of EXP/Level up system and RPG2 Message system. It lacks all functions related to RPG2 Menu, RPG2 Shop and RPG2 Battle.
-- LUA Script - precede every function and global member with lowercase name of script + '_main'
-- RPG Module 2 - Global Essential Functions for developers
-- Define the constants
PARTY_SIZE = 4
TIME_W = 145
TIME_B = 200
BATTLE_MESSAGE = 600
DIV_PARAM = 10
EQ_PARAM = 2
DIV_STAT = 25
DIV_SUB = 20
DIV_STR = 2
DIV_EXP = 2
INVENTORY_SIZE = 32
-- Legacy constants
NUM_DATASETS = 18
NUM_INV = 14
NUM_STATES = 8
NUM_SLOTS = 7
NUM_COUNTERS = 9999
-- Define tables for character status
g_CharacterHP = {}
g_CharacterMAXHP = {}
g_CharacterMP = {}
g_CharacterMAXMP = {}
g_CharacterStatus = {}
g_CharacterStatusLeft = {}
g_CharacterEXP = {}
g_CharacterLevel = {}
g_CharacterPower = {}
g_CharacterDefence = {}
g_CharacterAgility = {}
g_CharacterWisdom = {}
g_CharacterAccuracy = {}
g_CharacterBase = {}
-- Define tables for character equipment
g_CharacterWeapon = {}
g_CharacterArmor = {}
g_CharacterAccessory = {}
g_CharacterEqEffect = {}
g_CharacterPWRBonus = {}
g_CharacterDEFBonus = {}
g_CharacterAGIBonus = {}
g_CharacterACCBonus = {}
g_CharacterWISBonus = {}
g_CharacterMAGBonus = {}
-- Define tables for character name and class
g_CharacterName = {}
g_CharacterClass = {}
g_CharacterSlot = {}
-- Define tables for level up system
g_CharacterThreshold = {}
g_CharacterToNextLevel = {}
Flag_LevelUp = {}
-- Define tables for neutral NPC:s
NPCString = {}
-- Define tables for battle system
BCommandName = {}
BCommandDescription = {}
BCommandTargets = {}
BCommandType = {}
BCommandSelfStatus = {}
BCommandTargetStatus = {}
BCommandIsEscape = {}
BCommandIsExamine = {}
BCommandAnimation = {}
-- Define tables for battle narration
BCommandAction = {}
BCommandAction[1] = {}
BCommandAction[2] = {}
BCommandAction[3] = {}
BCommandAction[4] = {}
ChosenBCommand = {}
ChosenBTarget = {}
ChosenBSpell = {}
ChosenBItem = {}
EnemyBCommands = {}
EnemyBCommand = {}
EnemyBTarget = {}
EnemyBSpell = {}
EnemyBItem = {}
Flag_Started = {}
Flag_Finished = {}
Flag_Voice = {}
CanEscape = {}
EscapeTimer = {}
VenomDamage = {}
-- Define tables for menu system
ActiveCommand = {}
ItemMenuString = {}
MenuInfoString = {}
MainMenuString = {}
MainMenuString[1] = {}
MenuInfoString[1] = {}
MenuInfoString[2] = {}
-- Define tables for party system
ClassName = {}
ClassSpellLevel = {}
ClassStatBoost = {}
BattleCommand = {}
-- Define tables for Status system
StatusName = {}
StatusDuration = {}
Status_PWR = {}
Status_DEF = {}
Status_AGI = {}
Status_ACC = {}
Status_WIS = {}
Status_Venom = {}
-- Define tables to read databases
Data = {}
DataSlot = {}
DataAmount = {}
DataSpellCost = {} -- Special table used only by Spells
DataPrice = {} -- Special table used only by Shops
-- Define tables for inventory
g_Inv = {}
g_Inv[1] = {}
g_Inv[2] = {} -- Special items
g_Inv[3] = {} -- Quest items (TBA)
g_Inv[4] = {} -- Weapons
g_Inv[5] = {} -- Armor
g_Inv[6] = {} -- Accessory
g_Inv[11] = {} -- Character 1 spells
g_Inv[12] = {} -- Character 2 spells
g_Inv[13] = {} -- Character 3 spells
g_Inv[14] = {} -- Character 4 spells -- More of these will be created when a new character is introduced...
g_Inv[21] = {} -- General items (shop)
g_Inv[22] = {} -- Utility items (shop)
g_Inv[23] = {} -- Rare items (shop)
g_Inv[24] = {} -- Weapons (shop)
g_Inv[25] = {} -- Armor (shop)
g_Inv[26] = {} -- Accessory (shop)
-- Define tables for inventory (LEGACY) -----
InvItem = {}
InvWeapon = {}
InvArmor = {}
InvAccessory = {}
-- Define tables for item statistics
Inv_Name = {}
Inv_Description = {}
Inv_Target = {}
Inv_BTarget = {}
Inv_Effect = {}
Inv_Price = {}
Inv_Class = {} -- Special table only used by Equipment
Inv_Strength = {} -- Special table only used by Equipment
Inv_MPCost = {} -- Special table only used by Spells
Inv_SpellLevel = {} -- Special table only used by Spells
-- Define tables for usable items
Inv_Name[1] = {}
Inv_Description[1] = {}
Inv_Target[1] = {}
Inv_BTarget[1] = {}
Inv_Effect[1] = {}
Inv_Price[1] = {}
Inv_Class[1] = {}
-- Define tables for utility items
Inv_Name[2] = {}
Inv_Description[2] = {}
Inv_Target[2] = {}
Inv_BTarget[2] = {}
Inv_Effect[2] = {}
Inv_Price[2] = {}
Inv_Class[2] = {}
-- Define tables for quest items
Inv_Name[3] = {}
Inv_Description[3] = {}
Inv_Target[3] = {}
Inv_BTarget[3] = {}
Inv_Effect[3] = {}
Inv_Price[3] = {}
Inv_Class[3] = {}
-- Define tables for weapons
Inv_Name[4] = {}
Inv_Description[4] = {}
Inv_Target[4] = {}
Inv_BTarget[4] = {}
Inv_Effect[4] = {}
Inv_Price[4] = {}
Inv_Class[4] = {}
Inv_Strength[4] = {}
-- Define tables for armor
Inv_Name[5] = {}
Inv_Description[5] = {}
Inv_Target[5] = {}
Inv_BTarget[5] = {}
Inv_Effect[5] = {}
Inv_Price[5] = {}
Inv_Class[5] = {}
Inv_Strength[5] = {}
-- Define tables for accessories
Inv_Name[6] = {}
Inv_Description[6] = {}
Inv_Target[6] = {}
Inv_BTarget[6] = {}
Inv_Effect[6] = {}
Inv_Price[6] = {}
Inv_Class[6] = {}
Inv_Strength[6] = {}
-- Define tables for spells
Inv_Name[10] = {}
Inv_Description[10] = {}
Inv_Target[10] = {}
Inv_BTarget[10] = {}
Inv_Effect[10] = {}
Inv_Price[10] = {}
Inv_MPCost[10] = {}
Inv_SpellLevel[10] = {}
-- Define tables for enemy characters
g_EnemyHP = {}
g_EnemyMAXHP = {}
g_EnemyMP = {}
g_EnemyMAXMP = {}
g_EnemyStatus = {}
g_EnemyStatusLeft = {}
g_EnemyPower = {}
g_EnemyDefence = {}
g_EnemyAgility = {}
g_EnemyAccuracy = {}
g_EnemyWisdom = {}
g_EnemyGold = {}
g_EnemyItem = {}
g_EnemyEXP = {}
g_EnemyLevel = {}
g_EnemyClass = {} -- 1 = Attacker, 2 = Defender, 3 = Thief, 4 = Archer, 5 = Mage
g_EnemyBase = {}
g_EnemyWeapon = {}
g_EnemyArmor = {}
g_EnemyAccessory = {}
-- Define tables for party system
Flag_Join = {}
-- Define shop tables
g_ShopItem = {}
g_ShopType = {}
-- Define tables for animation system
ActiveAnimation = {} -- 1 = Stand, 2 = Hurt, 3 = Attack
StandStartFrame = {}
StandEndFrame = {}
HurtStartFrame = {}
HurtEndFrame = {}
AttackStartFrame = {}
AttackEndFrame = {}
WalkStartFrame = {}
WalkEndFrame = {}
SpecialStartFrame = {}
SpecialEndFrame = {}
BlockStartFrame = {}
BlockEndFrame = {}
-- Define tables for universal calculation
TempHP = {}
TempMAXHP = {}
TempMP = {}
TempMAXMP = {}
TempStatus = {}
TempStatusLeft = {}
TempEXP = {}
TempLevel = {}
TempPower = {}
TempDefence = {}
TempAgility = {}
TempAccuracy = {}
TempWisdom = {}
TempWeapon = {}
TempArmor = {}
TempAccessory = {}
TempCharacterSlot = {}
TempReady = {}
TempAlready = {}
TempPWRBonus = {}
TempDEFBonus = {}
TempAGIBonus = {}
TempACCBonus = {}
TempWISBonus = {}
TempMAGBonus = {}
TempPower2 = {}
TempDefence2 = {}
TempAgility2 = {}
TempAccuracy2 = {}
TempWisdom2 = {}
TempPreventStatus = {}
TempChosenCommand = {}
TempChosenTarget = {}
TempChosenSpell = {}
TempChosenItem = {}
TempName = {}
-- Define misc tables
EntityName = {}
EntityClass = {}
EntityBase = {}
EntityString = {}
ConversationDuration = {}
ConversationPhase = {}
SpellNumber = {}
NPC_ID = {}
-- Define the RPG data
RPG2_Database = require "scriptbank\\Moshroom\\rpg2_database"
-- Define files for RPG Module 1 data files
Data_File = {"RPG\\item_name.dat","RPG\\item_target.dat","RPG\\item_effect.dat","RPG\\item_description.dat","RPG\\item_price.dat","RPG\\weapon_name.dat","RPG\\weapon_price.dat","RPG\\armor_name.dat","RPG\\armor_price.dat","RPG\\accessory_name.dat","RPG\\accessory_target.dat","RPG\\accessory_effect.dat","RPG\\accessory_description.dat","RPG\\accessory_price.dat","RPG\\item_initial.dat","RPG\\weapon_initial.dat","RPG\\armor_initial.dat","RPG\\accessory_initial.dat","RPG\\rpg_state.dat"}
function rpg2_global_essentials_init(e)
-- Initiate RPG part flags
MenuActive = 0
ShopActive = 0
Battle_Phase = 0
-- Initiate the RPG variables
InitialParty = 1
-- Initiate the message system
R2Timed = 0
R2MsgTime = 0
R2CountTime = 0
R2MessageTime = 0
R2MessageString = 0
-- Initiate the Screen variables
ScreenX = GetDeviceWidth()
ScreenY = GetDeviceHeight()
-- Load the images (not yet available in version 1.0)
ImgCursor = LoadImage("scriptbank\\images\\RPG\\cursor.png")
-- Set the Cursor sprite
SprCursor = CreateSprite(ImgCursor)
SetSpriteSize(SprCursor,2,-1)
SetSpriteOffset(SprCursor,0,0)
SetSpritePosition(SprCursor,110,110)
-- Initiate the Battle variables
Active_Entity = 0
Battle_Phase = 0
Execute_Phase = 0
Test_Phase = 0
BtnTime = 0
PartySize = 4
ItemGained = 0
ArmorGained = 0
AccessoryGained = 0
WeaponGained = 0
-- Initiate the Battle flags
Flag_Win = 0
Flag_Lost = 0
Flag_Escape = 0
Flag_Failed = 0
Flag_Examine = 0
Flag_EnemyStats = 0
Flag_GotEXP = 0
Flag_Steal = 0
Flag_Animation = 0
Flag_Sound = 0
-- Initiate the Item flags
Flag_Usable = 0
-- Initiate the Global ID variable
GlobalID = e
-- Initiate the Utility item variables
g_Flag_Lantern = 0
g_Flag_Scavenger = 0
g_Flag_Spyglass = 0
-- Initiate the Battle variables
g_DropBonus = 0
-- Initiate the options
g_BasicMessageTime = 1000
g_BattleMessageTime = 600
-- Initiate the menu system
ActiveMenu = 0
Flag_MenuCall = 1
Flag_MenuActive = 0
-- Initiate variables for memory
QuantityReady = 0
QuantityAlready = 0
QuantityLearn = 0
ActiveStudent = 0
OriginX = 0
OriginY = 0
OriginZ = 0
Flag_Continue = 0
-- Call the RPG data
RPG2_Database.init(e)
end
-- RPG MODULE VERSION 2 GLOBAL FUNCTIONS --
-- INITIATION FUNCTIONS --
function RPG2_Initiate()
-- Initiate the characters
for i = 1,InitialParty do
-- Fill a CharacterSlot
g_CharacterSlot[i] = i
-- Initiate the character
g_CharacterHP[i] = 60
g_CharacterMAXHP[i] = 60
g_CharacterMP[i] = 40
g_CharacterMAXMP[i] = 40
g_CharacterStatus[i] = 0
g_CharacterStatusLeft[i] = -1
g_CharacterEXP[i] = 0
g_CharacterLevel[i] = 1
g_CharacterPower[i] = 4
g_CharacterDefence[i] = 4
g_CharacterAgility[i] = 4
g_CharacterAccuracy[i] = 4
g_CharacterWisdom[i] = 4
g_CharacterWeapon[i] = nil
g_CharacterArmor[i] = nil
g_CharacterAccessory[i] = nil
g_CharacterThreshold[i] = 0
g_CharacterToNextLevel[i] = 0
g_CharacterEqEffect[i] = 0
-- Set the LevelUp flag
Flag_LevelUp[i] = 0
end
-- Save player position
OriginX = g_PlayerPosX
OriginY = g_PlayerPosY
OriginZ = g_PlayerPosZ
-- Save the number of lives
Flag_Continue = g_PlayerLives
-- Activate the Flag_Init to prevent further initiateions
g_Flag_Initiate = 1
end
function RPG2_Initiate_Friendly_Character(Slot,Class,e)
-- Initiate the character
g_CharacterHP[Slot] = 60
g_CharacterMAXHP[Slot] = 60
g_CharacterMP[Slot] = 40
g_CharacterMAXMP[Slot] = 40
g_CharacterStatus[Slot] = 0
g_CharacterStatusLeft[Slot] = -1
-- Calculate the base statistic
g_CharacterBase[e] = 4
g_CharacterLevel[Slot] = 1
g_CharacterEXP[Slot] = EntityBase[e]
-- Set the level up flag to -1 to enable initial level calculation in RPG2_Character_Development() function
Flag_LevelUp[Slot] = -1
-- Set the base statistics depending on the Class
if ClassStatBoost[Class] == 1 then
g_CharacterPower[Slot] = g_CharacterBase[e] + 1
g_CharacterDefence[Slot] = g_CharacterBase[e]
g_CharacterAgility[Slot] = g_CharacterBase[e]
g_CharacterAccuracy[Slot] = g_CharacterBase[e]
g_CharacterWisdom[Slot] = g_CharacterBase[e]
elseif ClassStatBoost[Class] == 2 then
g_CharacterPower[Slot] = g_CharacterBase[e]
g_CharacterDefence[Slot] = g_CharacterBase[e] + 1
g_CharacterAgility[Slot] = g_CharacterBase[e]
g_CharacterAccuracy[Slot] = g_CharacterBase[e]
g_CharacterWisdom[Slot] = g_CharacterBase[e]
elseif ClassStatBoost[Class] == 3 then
g_CharacterPower[Slot] = g_CharacterBase[e]
g_CharacterDefence[Slot] = g_CharacterBase[e]
g_CharacterAgility[Slot] = g_CharacterBase[e] + 1
g_CharacterAccuracy[Slot] = g_CharacterBase[e]
g_CharacterWisdom[Slot] = g_CharacterBase[e]
elseif ClassStatBoost[Class] == 4 then
g_CharacterPower[Slot] = g_CharacterBase[e]
g_CharacterDefence[Slot] = g_CharacterBase[e]
g_CharacterAgility[Slot] = g_CharacterBase[e]
g_CharacterAccuracy[Slot] = g_CharacterBase[e] + 1
g_CharacterWisdom[Slot] = g_CharacterBase[e]
elseif ClassStatBoost[Class] == 5 then
g_CharacterPower[Slot] = g_CharacterBase[e]
g_CharacterDefence[Slot] = g_CharacterBase[e]
g_CharacterAgility[Slot] = g_CharacterBase[e]
g_CharacterAccuracy[Slot] = g_CharacterBase[e]
g_CharacterWisdom[Slot] = g_CharacterBase[e] + 1
else
-- Undefined, return default
g_CharacterPower[Slot] = g_CharacterBase[e]
g_CharacterDefence[Slot] = g_CharacterBase[e]
g_CharacterAgility[Slot] = g_CharacterBase[e]
g_CharacterAccuracy[Slot] = g_CharacterBase[e]
g_CharacterWisdom[Slot] = g_CharacterBase[e]
end
g_CharacterWeapon[Slot] = nil
g_CharacterArmor[Slot] = nil
g_CharacterAccessory[Slot] = nil
g_CharacterThreshold[Slot] = 0
g_CharacterToNextLevel[Slot] = 0
g_CharacterEqEffect[Slot] = 0
-- Fill a CharacterSlot
g_CharacterSlot[Slot] = Slot
g_CharacterName[Slot] = EntityName[e]
g_CharacterClass[Slot] = Class
--DEBUG STUFF
--PromptDuration(g_CharacterEXP[Slot] .. " " ..g_CharacterLevel[Slot],2000)
end
function RPG2_Initiate_Enemy(e)
-- Set enemy HP and MP
g_EnemyMAXHP[e] = g_Entity[e]['health'] + math.random(1,5)
g_EnemyHP[e] = g_EnemyMAXHP[e]
g_EnemyMAXMP[e] = (g_Entity[e]['health'] / 2) + math.random(1,5)
g_EnemyMP[e] = g_EnemyMAXMP[e]
g_EnemyStatus[e] = 1
g_EnemyStatusLeft[e] = -1
-- Balance enemy statistics to 2 categories
if g_Entity[e]['health'] < 100 then -- Weak
g_EnemyBase[e] = math.ceil(g_Entity[e]['health'] / 100)
-- Set enemy base statistics
g_EnemyPower[e] = math.ceil(g_EnemyPower[e] * g_EnemyBase[e]) + math.random(0,1)
g_EnemyDefence[e] = math.ceil(g_EnemyDefence[e] * g_EnemyBase[e]) + math.random(0,1)
g_EnemyAgility[e] = math.ceil(g_EnemyAgility[e] * g_EnemyBase[e]) + math.random(0,1)
g_EnemyAccuracy[e] = math.ceil(g_EnemyAccuracy[e] * g_EnemyBase[e]) + math.random(0,1)
g_EnemyWisdom[e] = math.ceil(g_EnemyWisdom[e] * g_EnemyBase[e]) + math.random(0,1)
else -- Strong
g_EnemyBase[e] = math.floor(g_Entity[e]['health'] / DIV_STAT)
-- Set enemy base statistics
g_EnemyPower[e] = g_EnemyPower[e] + g_EnemyBase[e] + math.random(-1,1)
g_EnemyDefence[e] = g_EnemyDefence[e] + g_EnemyBase[e] + math.random(-1,1)
g_EnemyAgility[e] = g_EnemyAgility[e] + g_EnemyBase[e] + math.random(-1,1)
g_EnemyAccuracy[e] = g_EnemyAccuracy[e] + g_EnemyBase[e] + math.random(-1,1)
g_EnemyWisdom[e] = g_EnemyWisdom[e] + g_EnemyBase[e] + math.random(-1,1)
end
-- Set the EXP and Gold
g_EnemyEXP[e] = math.floor(g_Entity[e]['health'] / DIV_EXP)
g_EnemyGold[e] = math.random(100,200)
-- Set the enemy Level
g_EnemyLevel[e] = 1
end
-- BACKGROUND FUNCTIONS --
function RPG2_Options()
-- Field Message Speed
if g_BasicMessageSpeed == nil then
g_BasicMessageSpeed = 2
elseif g_BasicMessageSpeed == 1 then -- Fast
g_BasicMessageTime = 500
elseif g_BasicMessageSpeed == 2 then -- Default
g_BasicMessageTime = 800
elseif g_BasicMessageSpeed == 3 then -- Slow
g_BasicMessageTime = 1200
else
-- Warning, return default
PromptDuration("Warning 11.1: Unknown value (RPG2_Options)",ERROR_MESSAGE)
g_BasicMessageSpeed = 2
end
-- Battle Message Speed
if g_BattleMessageSpeed == nil then
g_BattleMessageSpeed = 2
elseif g_BattleMessageSpeed == 1 then -- Fast
g_BattleMessageTime = 500
elseif g_BattleMessageSpeed == 2 then -- Default
g_BattleMessageTime = 800
elseif g_BattleMessageSpeed == 3 then -- Slow
g_BattleMessageTime = 1200
else
-- Warning, return default
PromptDuration("Warning 11.2: Unknown value (RPG2_Options)",ERROR_MESSAGE)
g_BattleMessageSpeed = 2
end
-- Message Style
if g_MessageWindow == nil then
g_MessageWindow = 1
end
-- Text Size
if g_TextSize == nil then
if ScreenY < 768 then
-- Low resolution -> small text
g_TextSize = 2
else
-- Normal resolition -> default text
g_TextSize = 1
end
end
-- Mouse support
if g_EnableMouse == nil then
g_EnableMouse = 0
end
end
function RPG2_Status()
-- Process the status parameter
for i = 1,PARTY_SIZE do
-- Make sure that the character exists
if g_CharacterSlot[i] ~= nil then
if g_CharacterHP[g_CharacterSlot[i]] <= 0 then -- Process the fatal state
g_CharacterStatus[g_CharacterSlot[i]] = 0 -- KO
elseif g_CharacterStatus[g_CharacterSlot[i]] < 4 then -- Process the un-abnormal states
if g_CharacterHP[g_CharacterSlot[i]] <= g_CharacterMAXHP[g_CharacterSlot[i]] and g_CharacterHP[g_CharacterSlot[i]] >= g_CharacterMAXHP[g_CharacterSlot[i]] / 4 then
g_CharacterStatus[g_CharacterSlot[i]] = 1 -- Normal
elseif g_CharacterHP[g_CharacterSlot[i]] < g_CharacterMAXHP[g_CharacterSlot[i]] / 4 then
g_CharacterStatus[g_CharacterSlot[i]] = 2 -- Critical
elseif g_CharacterHP[g_CharacterSlot[i]] > g_CharacterMAXHP[g_CharacterSlot[i]] or g_CharacterMP[g_CharacterSlot[i]] > g_CharacterMAXMP[g_CharacterSlot[i]] then
g_CharacterStatus[g_CharacterSlot[i]] = 3 -- Overdrive
end
end
end
end
end
function RGP2_Equipment()
-- Process the status parameter
for i = 1,PARTY_SIZE do
-- Test whether the character exists
if g_CharacterSlot[i] ~= nil then
-- Process PWR Bonus
if g_CharacterWeapon[g_CharacterSlot[i]] == nil or g_CharacterWeapon[g_CharacterSlot[i]] == 0 then
g_CharacterPWRBonus[g_CharacterSlot[i]] = 0
else
g_CharacterPWRBonus[g_CharacterSlot[i]] = Inv_Strength[4][g_CharacterWeapon[g_CharacterSlot[i]]]
end
-- Provess DEF Bonus
if g_CharacterArmor[g_CharacterSlot[i]] == nil or g_CharacterArmor[g_CharacterSlot[i]] == 0 then
g_CharacterDEFBonus[g_CharacterSlot[i]] = 0
else
g_CharacterDEFBonus[g_CharacterSlot[i]] = Inv_Strength[5][g_CharacterArmor[g_CharacterSlot[i]]]
end
-- Process AGI, ACC and WIS Bonuses
if g_CharacterAccessory[g_CharacterSlot[i]] == nil or g_CharacterAccessory[g_CharacterSlot[i]] == 0 then
-- If there is no Accessory
g_CharacterAGIBonus[g_CharacterSlot[i]] = 0
g_CharacterACCBonus[g_CharacterSlot[i]] = 0
g_CharacterWISBonus[g_CharacterSlot[i]] = 0
else
if Inv_Target[6][g_CharacterAccessory[g_CharacterSlot[i]]] == 41 then
-- If the Accessory affects AGI
g_CharacterAGIBonus[g_CharacterSlot[i]] = Inv_Effect[6][g_CharacterAccessory[g_CharacterSlot[i]]]
g_CharacterACCBonus[g_CharacterSlot[i]] = 0
g_CharacterWISBonus[g_CharacterSlot[i]] = 0
elseif Inv_Target[6][g_CharacterAccessory[g_CharacterSlot[i]]] == 51 then
-- If the Accessory affects ACC
g_CharacterAGIBonus[g_CharacterSlot[i]] = 0
g_CharacterACCBonus[g_CharacterSlot[i]] = Inv_Effect[6][g_CharacterAccessory[g_CharacterSlot[i]]]
g_CharacterWISBonus[g_CharacterSlot[i]] = 0
elseif Inv_Target[6][g_CharacterAccessory[g_CharacterSlot[i]]] == 61 then
-- If the Accessory affects WIS
g_CharacterAGIBonus[g_CharacterSlot[i]] = 0
g_CharacterACCBonus[g_CharacterSlot[i]] = 0
g_CharacterWISBonus[g_CharacterSlot[i]] = Inv_Effect[6][g_CharacterAccessory[g_CharacterSlot[i]]]
else
-- If the Accessory doesn't affect stats
g_CharacterAGIBonus[g_CharacterSlot[i]] = 0
g_CharacterACCBonus[g_CharacterSlot[i]] = 0
g_CharacterWISBonus[g_CharacterSlot[i]] = 0
end
end
-- Process the MAG Bonus
if g_CharacterWisdom[g_CharacterSlot[i]] + g_CharacterWISBonus[g_CharacterSlot[i]] >= 50 then
g_CharacterMAGBonus[g_CharacterSlot[i]] = 1
else
g_CharacterMAGBonus[g_CharacterSlot[i]] = 0
end
end
end
end
function RPG2_Character_Development()
-- Process the level up
for i = 1,PARTY_SIZE do
-- Process the threshold
if g_CharacterSlot[i] ~= nil then
g_CharacterThreshold[g_CharacterSlot[i]] = g_CharacterLevel[g_CharacterSlot[i]] * LEVEL_PARAM_A + (g_CharacterLevel[g_CharacterSlot[i]] - 1) * LEVEL_PARAM_B + (g_CharacterLevel[g_CharacterSlot[i]] - 2) * LEVEL_PARAM_C
g_CharacterToNextLevel[g_CharacterSlot[i]] = g_CharacterThreshold[g_CharacterSlot[i]] - g_CharacterEXP[g_CharacterSlot[i]]
-- Test whether the threshold is reached
if g_CharacterEXP[g_CharacterSlot[i]] >= g_CharacterThreshold[g_CharacterSlot[i]] then
-- Use while loop to process multiple levelings correctly
while g_CharacterEXP[g_CharacterSlot[i]] >= g_CharacterThreshold[g_CharacterSlot[i]] do
-- Level up
g_CharacterLevel[g_CharacterSlot[i]] = g_CharacterLevel[g_CharacterSlot[i]] + 1
-- Recalculate the threshold
g_CharacterThreshold[g_CharacterSlot[i]] = g_CharacterLevel[g_CharacterSlot[i]] * LEVEL_PARAM_A + (g_CharacterLevel[g_CharacterSlot[i]] - 1) * LEVEL_PARAM_B + (g_CharacterLevel[g_CharacterSlot[i]] - 2) * LEVEL_PARAM_C
-- Increase the MAXHP and MAXMP
g_CharacterMAXHP[g_CharacterSlot[i]] = g_CharacterMAXHP[g_CharacterSlot[i]] + LEVEL_PARAM_B + (g_CharacterLevel[g_CharacterSlot[i]] - 5) * LEVEL_PARAM_C + math.random(0,5)
g_CharacterMAXMP[g_CharacterSlot[i]] = g_CharacterMAXHP[g_CharacterSlot[i]] + (g_CharacterLevel[g_CharacterSlot[i]] * LEVEL_PARAM_C) + math.random(0,5)
-- Increase the RPG statistics
local StatGrowth = math.random(1,5)
if StatGrowth == 1 then
g_CharacterPower[g_CharacterSlot[i]] = g_CharacterPower[g_CharacterSlot[i]] + 1
elseif StatGrowth == 2 then
g_CharacterDefence[g_CharacterSlot[i]] = g_CharacterDefence[g_CharacterSlot[i]] + 1
elseif StatGrowth == 3 then
g_CharacterAgility[g_CharacterSlot[i]] = g_CharacterAgility[g_CharacterSlot[i]] + 1
elseif StatGrowth == 4 then
g_CharacterAccuracy[g_CharacterSlot[i]] = g_CharacterAccuracy[g_CharacterSlot[i]] + 1
elseif StatGrowth == 5 then
g_CharacterWisdom[g_CharacterSlot[i]] = g_CharacterWisdom[g_CharacterSlot[i]] + 1
else
-- Error, ignore
PromptDuration("Warning 103: Unknown statistic type (RPG2_Character_Development)",ERROR_MESSAGE)
end
-- If the character is wearing a status boost item, increase an additional statistic
if g_CharacterEqEffect[g_CharacterSlot[i]] == 20 then
g_CharacterPower[g_CharacterSlot[i]] = g_CharacterPower[g_CharacterSlot[i]] + 1
elseif g_CharacterEqEffect[g_CharacterSlot[i]] == 30 then
g_CharacterDefence[g_CharacterSlot[i]] = g_CharacterDefence[g_CharacterSlot[i]] + 1
elseif g_CharacterEqEffect[g_CharacterSlot[i]] == 40 then
g_CharacterAgility[g_CharacterSlot[i]] = g_CharacterAgility[g_CharacterSlot[i]] + 1
elseif g_CharacterEqEffect[g_CharacterSlot[i]] == 50 then
g_CharacterAccuracy[g_CharacterSlot[i]] = g_CharacterAccuracy[g_CharacterSlot[i]] + 1
elseif g_CharacterEqEffect[g_CharacterSlot[i]] == 60 then
g_CharacterWisdom[g_CharacterSlot[i]] = g_CharacterWisdom[g_CharacterSlot[i]] + 1
end
-- In certain levels, give characters an extra boost to certain statistics depending on class
if g_CharacterLevel[g_CharacterSlot[i]] % 3 == 0 then
if ClassStatBoost[g_CharacterClass[g_CharacterSlot[i]]] == 1 then
g_CharacterPower[g_CharacterSlot[i]] = g_CharacterPower[g_CharacterSlot[i]] + 1
elseif ClassStatBoost[g_CharacterClass[g_CharacterSlot[i]]] == 2 then
g_CharacterAgility[g_CharacterSlot[i]] = g_CharacterAgility[g_CharacterSlot[i]] + 1
elseif ClassStatBoost[g_CharacterClass[g_CharacterSlot[i]]] == 3 then
g_CharacterWisdom[g_CharacterSlot[i]] = g_CharacterWisdom[g_CharacterSlot[i]] + 1
elseif ClassStatBoost[g_CharacterClass[g_CharacterSlot[i]]] == 4 then
g_CharacterAccuracy[g_CharacterSlot[i]] = g_CharacterAccuracy[g_CharacterSlot[i]] + 1
elseif ClassStatBoost[g_CharacterClass[g_CharacterSlot[i]]] == 5 then
g_CharacterWisdom[g_CharacterSlot[i]] = g_CharacterWisdom[g_CharacterSlot[i]] + 1
end
end
end -- end while
-- Check the level up flag
if Flag_LevelUp[g_CharacterSlot[i]] == -1 then
-- In the initial calculation, fill in HP and MP
g_CharacterHP[g_CharacterSlot[i]] = g_CharacterMAXHP[g_CharacterSlot[i]]
g_CharacterMP[g_CharacterSlot[i]] = g_CharacterMAXMP[g_CharacterSlot[i]]
-- Set the flag off
Flag_LevelUp[g_CharacterSlot[i]] = 0
else
-- In further level ups, set the flag on
Flag_LevelUp[g_CharacterSlot[i]] = 1
end
end -- end if
end
end -- end for
end -- end function
function RPG2_Message_Window_Process()
-- Test whether global STimed flag is 1
if R2Timed == 1 then
-- If the timer is 0, initiate it
if R2CountTime == 0 then
R2CountTime = g_Time
R2MsgTime = g_Time + R2MessageTime
end
-- If the timer is running, use it
if R2CountTime ~= 0 then
R2CountTime = g_Time
Panel(20,45,80,55)
TextCenterOnX(50,50,g_TextSize,R2MessageString)
end
-- If the the timer reaches goal, reset it and deactivate prompt
if R2CountTime > R2MsgTime then
R2Timed = 0
R2MsgTime = 0
R2CountTime = 0
end
end
end
-- MAIN FUNCTIONS : BATTLE SYSTEM --
function RPG2_Enemy_Encounter(e)
-- Only encounter if battle is not already started
if Battle_Phase == 0 then
-- Disable RPG menu and reset menu process
Flag_MenuCall = 0
ActiveMenu = 0
-- Wait and show a message, then initiate battle
RPG2_Wait(2000)
if Flag_Wait == nil then
-- Do nothing
elseif Flag_Wait == 0 then
-- Show the attack message
RPG2_Message(EntityName[e] .. " attacks!",0,0,0,e)
-- Turn camera towards the enemy
RPG2_Camera_FixTo(e) -- Note: Replace this with Rotate command, when it works
elseif Flag_Wait >= 1 then
-- Flag the encountered enemy as an enemy
Flag_Started[e] = 1
-- Start battle
Battle_Phase = 1
-- Dispose the Wait flag
Flag_Wait = nil
else
-- Fatal error, abort battle
PromptDuration("Error 12: Unknown flag (RPG2_Enemy_Encounter)",ERROR_MESSAGE)
Battle_Phase = 9
end
end
end
function RPG2_Mode_Battle(BattleType,EnemyID)
-- NOTE: This is a placeholder function to test other battle-related scripts
-- Move to the relevant battle phase
if Battle_Phase == 1 then -- Initiate
Battle_Phase = 2
end
--DEBUG STUFF
Prompt("Battle Phase: " .. Battle_Phase)
end
function RPG2_Window_Game_Over(e)
-- Show the Game Over message
RPG2_Message("Game Over!",0,0,0,e)
UnFreezePlayer()
end
-- CALL FUNCTIONS : BASE --
function RPG2_Draw_Cursor(X,Y,SizeX,SizeY,NumColumns,Command)
-- Calculate the Y fix if neccessary (too low resolution)
RPG2_Calculate_Low_Resolution_Fix()
-- Calculate Cursor coordinates
if NumColumns == 1 then
PosX = X
PosY = Y + (Command - 1) * SizeY - FixY
PosX2 = PosX + SizeX
PosY2 = PosY + SizeY - FixY
else
-- Calculate the X position
PosX = X + ((Command - 1) % NumColumns) * SizeX
-- Caluclate the Y position
PosY = Y + (((Command - 1) - ((Command - 1) % NumColumns)) * SizeY - FixY)/NumColumns
-- Calculate size
PosX2 = PosX + SizeX
PosY2 = PosY + SizeY - FixY
end
-- Draw Cursor
Panel(PosX,PosY,PosX2,PosY2)
end
function RPG2_Control_Cursor(NumColumns,NumMenuItems)
-- The number of axis depends on the number of columns
if NumColumns == 1 then
-- Update menu when player presses up/down
if g_KeyPressW == 1 and g_Time > BtnTime or g_MouseWheel > 0 and g_Time > BtnTime and g_EnableMouse == 1 then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] - 1
end
if g_KeyPressS == 1 and g_Time > BtnTime or g_MouseWheel < 0 and g_Time > BtnTime and g_EnableMouse == 1 then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] + 1
end
-- Set limits for the command - Wrap
if ActiveCommand[ActiveMenu] > NumMenuItems then
ActiveCommand[ActiveMenu] = 1
end
if ActiveCommand[ActiveMenu] < 1 then
ActiveCommand[ActiveMenu] = NumMenuItems
end
elseif NumColumns > 1 then
-- Update menu when player presses up/down/left/right
if g_KeyPressA == 1 and g_Time > BtnTime or g_MouseWheel > 0 and g_Time > BtnTime and g_EnableMouse == 1 then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] - 1
end
if g_KeyPressW == 1 and g_Time > BtnTime then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] - NumColumns
end
if g_KeyPressD == 1 and g_Time > BtnTime or g_MouseWheel < 0 and g_Time > BtnTime and g_EnableMouse == 1 then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] + 1
end
if g_KeyPressS == 1 and g_Time > BtnTime then
PlayNon3DSound(GlobalID,0)
BtnTime = g_Time + TIME_W
ActiveCommand[ActiveMenu] = ActiveCommand[ActiveMenu] + NumColumns
end
-- Set limits for the command - No wrap
if ActiveCommand[ActiveMenu] > NumMenuItems then
ActiveCommand[ActiveMenu] = NumMenuItems
end
if ActiveCommand[ActiveMenu] < 1 then
ActiveCommand[ActiveMenu] = 1
end
else
-- Fatal error
PromptDuration("Error 13.1: Unknown column number (Control_Cursor)",ERROR_MESSAGE)
end
end
function RPG2_Message(MsgString1,MsgString2,MsgType,MsgDuration,e)
-- Only show message when Menu, Shop and Battle are not active
if MenuActive == 0 and ShopActive == 0 and Battle_Phase == 0 then
-- Only show message window, if it's set on from the Menu
if g_MessageWindow == 1 then
if MsgType == 0 then -- 1 line, centered
Panel(20,45,80,55)
TextCenterOnX(50,50,g_TextSize,MsgString1)
elseif MsgType == 1 then -- 1st line aligned to left, 2nd to center
Panel(20,73,80,95)
Text(22,78,g_TextSize,"<" .. EntityName[e] .. ">")
Text(22,83,g_TextSize,MsgString1)
TextCenterOnX(50,90,g_TextSize,"-- " .. MsgString2 .. " --")
elseif MsgType == 2 then -- 1st and 2nd lines aligned to left
Panel(20,73,80,95)
Text(22,78,g_TextSize,"<" .. EntityName[e] .. ">")
Text(22,83,g_TextSize,MsgString1)
Text(22,88,g_TextSize,MsgString2)
elseif MsgType == 3 then -- 1 line with question
Panel(20,73,80,95)
Text(22,78,g_TextSize,"<" .. EntityName[e] .. ">")
Text(22,83,g_TextSize,MsgString1)
-- Activate the menu, inactivate other commands
FreezePlayer()
FreezeAI()
ActivateMouse()
-- Open an entity menu
ActiveMenu = e
-- Prevent menu call (must be turned back on after the question is answered)
Flag_MenuCall = 0
-- Initiate the active command
if ActiveCommand[ActiveMenu] == nil then
ActiveCommand[ActiveMenu] = 1
end
RPG2_Control_Cursor(2,2)
RPG2_Draw_Cursor(25,86,25,3,2,ActiveCommand[ActiveMenu])
-- Draw the coices
TextCenterOnX(37.5,89.5,g_TextSize,"Yes")
TextCenterOnX(62.5,89.5,g_TextSize,"No")
elseif MsgType == 4 then -- One line only
Panel(20,78,80,95)
Text(22,83,g_TextSize,"<" .. EntityName[e] .. ">")
Text(22,88,g_TextSize,MsgString1)
elseif MsgType == 5 then -- Game Over
Panel(20,45,80,62)
TextCenterOnX(50,50,g_TextSize,MsgString1)
-- Activate the menu, inactivate other commands
FreezePlayer()
FreezeAI()
ActivateMouse()
-- Open an entity menu
ActiveMenu = e
-- Prevent menu call (must be turned back on after the question is answered)
Flag_MenuCall = 0
-- Initiate the active command
if ActiveCommand[ActiveMenu] == nil then
ActiveCommand[ActiveMenu] = 1
end
RPG2_Control_Cursor(2,2)
RPG2_Draw_Cursor(25,53,25,3,2,ActiveCommand[ActiveMenu])
-- Draw the coices
TextCenterOnX(37.5,56.5,g_TextSize,"Continue")
TextCenterOnX(62.5,56.5,g_TextSize,"End")
elseif MsgType == 10 then -- Timed one-line message
-- Use global TMessageString variable to store the message string
R2MessageString = MsgString1
R2MessageTime = MsgDuration
-- Use global MTimed flag to activate the message window in RPG2_Message_Window_Process() function
R2Timed = 1
end
else
if MsgType < 10 then -- 10 -> Timed Messages
-- Show non-timed prompt
Prompt(MsgString1 .. " " .. MsgString2 .. ".")
else
-- Show timed prompt
PromptDuration(MsgString1 .. " " .. MsgString2 .. ".",MsgDuration)
end
end
elseif MenuActive == 0 and ShopActive == 0 and Battle_Phase > 0 then
-- Battle Messages are always one-lined and can only be shown centered
Panel(20,45,80,55)
TextCenterOnX(50,50,g_TextSize,MsgString1)
end
end
-- CALL FUNCTIONS : SUPPORT --
function RPG2_Wait(WDuration)
-- Special command that does 2 things during certain amount of time
if Flag_Wait == nil then
TimeWait = g_Time + WDuration
Flag_Wait = 0
else
if TimeWait < g_Time then
Flag_Wait = Flag_Wait + 1
TimeWait = g_Time + WDuration
end
end
-- Note: Remember to dispose Flag_Wait to prevent unneeded repeats
end
function RPG2_Calculate_Low_Resolution_Fix()
-- Do the necessary calculations for Y coordinate
if FixY == nil then
if ScreenY > 768 then
FixY = 0
else
FixY = 0.5
end
end
-- DEBUG STUFF
-- TextCenterOnX(50,40,1,ScreenX .. " : " .. ScreenY)
end
-- CALL FUNCTIONS : ENTITY --
function RPG2_Camera_FixTo(e)
-- Get player distance to the entity
local DistanceX = g_PlayerPosX - g_Entity[e]['x']
local DistanceY = g_PlayerPosY - g_Entity[e]['y']
local DistanceZ = g_PlayerPosZ - g_Entity[e]['z']
-- Calculate the target angle
local AngleXT = 10 - (GetPlayerDistance(e) / 100)
local AngleYT = math.atan2(DistanceX,DistanceZ) * (180 / math.pi) - 180
-- Fix the value of Y angle
if AngleYT <= 0 then
AngleYT = 360 + AngleYT
elseif AngleYT > 360 then
AngleYT = AngleYT - 360
end
-- Freeze player
FreezePlayer()
-- Set the roation
SetFreezeAngle(AngleXT,AngleYT,g_PlayerAngZ)
-- Reactivate camera
UnFreezePlayer()
end
-- RPG MODULE VERSION 1 GLOBAL FUNCTIONS --
function Load_RPG_Data_modified()
-- Read data from RPG Module 1 dataset files
for DataRead = 1,NUM_DATASETS do
local File = io.open(Data_File[DataRead], "r")
if File ~= nil then
for Line = 1,NUM_INV do
-- 1 = Item Name
if DataRead == 1 then
Inv_Name[1][Line] = File:read("*l")
if Inv_Name[1][Line] == nil then
Inv_Name[1][Line] = "Package"
end
end
-- 2 = Item Target
if DataRead == 2 then
Inv_Target[1][Line] = tonumber(File:read("*l"))
if Inv_Target[1][Line] == nil then
Inv_Target[1][Line] = 99
end
-- Add the BTarget value 1, since RPG Module 1 doesn't have items that affect enemy
Inv_BTarget[1][Line] = 1
end
-- 3 = Item Effect
if DataRead == 3 then
Inv_Effect[1][Line] = tonumber(File:read("*l"))
if Inv_Effect[1][Line] == nil then
Inv_Effect[1][Line] = 1
end
end
-- 4 = Item Description
if DataRead == 4 then
Inv_Description[1][Line] = File:read("*l")
if Inv_Description[1][Line] == nil then
Inv_Description[1][Line] = "Generic item."
end
end
-- 5 = Item Price
if DataRead == 5 then
Inv_Price[1][Line] = tonumber(File:read("*l"))
if Inv_Price[1][Line] == nil then
Inv_Price[1][Line] = 10
end
end
-- 6 = Weapon Name
if DataRead == 6 then
Inv_Name[4][Line] = File:read("*l")
if Inv_Name[4][Line] == nil then
Inv_Name[4][Line] = "Staff"
end
-- Add Weapon parameters according to RPG Module 1 logic
Inv_Strength[4][Line] = Line * 2 -- Weapon strength has a rising curve
Inv_Description[4][Line] = "Increases attack power by " .. Line * 2 .. "."
-- Add default values for additional Weapon parameters
Inv_Class[4][Line] = 0 -- All weapons are universal
Inv_Target[4][Line] = 0
Inv_Effect[4][Line] = 1
Inv_BTarget[4][Line] = 9
end
-- 7 = Weapon Price
if DataRead == 7 then
Inv_Price[4][Line] = tonumber(File:read("*l"))
if Inv_Price[4][Line] == nil then
Inv_Price[4][Line] = 10
end
end
-- 8 = Armor Name
if DataRead == 8 then
Inv_Name[5][Line] = File:read("*l")
if Inv_Name[5][Line] == nil then
Inv_Name[5][Line] = "Armor"
end
-- Add Armor parameters according to RPG Module 1 logic
Inv_Strength[5][Line] = Line * 2 -- Armor strength has a rising curve
Inv_Description[5][Line] = "Increases defence by " .. Line * 2 .. "."
-- Add default values for additional Armor parameters
Inv_Class[5][Line] = 0 -- All Armor are universal
Inv_Target[5][Line] = 0
Inv_Effect[5][Line] = 1
Inv_BTarget[5][Line] = 9
end
-- 9 = Armor Price
if DataRead == 9 then
Inv_Price[5][Line] = tonumber(File:read("*l"))
if Inv_Price[5][Line] == nil then
Inv_Price[5][Line] = 10
end
end
-- 10 = Accessory Name
if DataRead == 10 then
Inv_Name[6][Line] = File:read("*l")
if Inv_Name[6][Line] == nil then
Inv_Name[6][Line] = "Ornament"
end
end
-- 11 = Accessory Target
if DataRead == 11 then
Inv_Target[6][Line] = tonumber(File:read("*l"))
if Inv_Target[6][Line] == nil then
Inv_Target[6][Line] = 99
end
-- Add default values for additional Accessory parameters
Inv_Class[6][Line] = 0 -- All Armor are universal
Inv_BTarget[6][Line] = 9
end
-- 12 = Accessory Effect
if DataRead == 12 then
Inv_Effect[6][Line] = tonumber(File:read("*l"))
if Inv_Effect[6][Line] == nil then
Inv_Effect[6][Line] = 1
end
end
-- 13 = Accessory Description
if DataRead == 13 then
Inv_Description[6][Line] = File:read("*l")
if Inv_Description[6][Line] == nil then
Inv_Description[6][Line] = "Nice to have, but does nothing."
end
end
-- 14 = Accessory Price
if DataRead == 14 then
Inv_Price[6][Line] = tonumber(File:read("*l"))
if Inv_Price[6][Line] == nil then
Inv_Price[6][Line] = 10
end
end
-- 15 = Initial Item
if DataRead == 15 then
g_Inv[1][Line] = tonumber(File:read("*l"))
if g_Inv[1][Line] == nil or g_Inv[1][Line] == 0 then
g_Inv[1][Line] = nil
end
end
-- 16 = Initial Weapon
if DataRead == 16 then
g_Inv[4][Line] = tonumber(File:read("*l"))
if g_Inv[4][Line] == nil or g_Inv[4][Line] == 0 then
g_Inv[4][Line] = nil
end
end
-- 17 = Initial Armor
if DataRead == 17 then
g_Inv[5][Line] = tonumber(File:read("*l"))
if g_Inv[5][Line] == nil or g_Inv[5][Line] == 0 then
g_Inv[5][Line] = nil
end
end
-- 18 = Initial Accessory
if DataRead == 18 then
g_Inv[6][Line] = tonumber(File:read("*l"))
if g_Inv[6][Line] == nil or g_Inv[6][Line] == 0 then
g_Inv[6][Line] = nil
end
end
end -- end for
File:close()
end -- end if
end -- end for
local SFile = io.open(Data_File[19], "r")
if SFile == nil then
-- If there is no file, use the default values
StatusName = {"Normal", "Critical", "Overdrive", "Feeble", "Weak", "Slow", "Blind", "Venom"}
else
-- If there is a File, read it and store it to State table
local SLine = 1
-- Store as many states as there are in the file
while true do
StatusName[SLine] = SFile:read("*l")
if StatusName[SLine] == nil then break end
SLine = SLine + 1
end
SFile:close()
end
end
function RPG_Initiate_modified()
-- If RPG Module 1 database files are used, load them
if DATABASE_FILES == 1 then
Load_RPG_Data_modified()
end
-- Set the legacy variables
if g_RPG_Gold == nil then
g_RPG_Gold = 0
end
-- Reset the Timer
if g_TimeCounter == nil then
g_TimeCounter = 0
end
if g_TimeSecond == nil then
g_TimeSecond = 0
end
if g_TimeMinute == nil then
g_TimeMinute = 0
end
if g_TimeHour == nil then
g_TimeHour = 0
end
end
function RPG_Timer_modified()
-- Run the Timer
if g_TimeCounter < g_Time then
g_TimeSecond = g_TimeSecond + 1
g_TimeCounter = g_Time + 1000
end
if g_TimeSecond >= 60 then
g_TimeMinute = g_TimeMinute + 1
g_TimeSecond = 0
end
if g_TimeMinute >= 60 then
g_TimeHour = g_TimeHour + 1
g_TimeMinute = 0
end
end
-- RPG MODULE VERSION 1 OUTDATED FUNCTIONS --
function RPG1_Legacy()
-- These functions are not used in the Party based system
-- Uncomment only if needed - note that these variables and functions need to be defined before used
-- (see the original lua files of RPG Module version 1)
-- Process RPG state for 1-player party
-- RPG_State()
-- -- Count leveling variables
-- g_RPG_Threshold = g_RPG_Level * LEVEL_PARAM_A + (g_RPG_Level - 1) * LEVEL_PARAM_B + (g_RPG_Level - 2) * LEVEL_PARAM_C
-- g_RPG_ToNextLevel = g_RPG_Threshold - g_RPG_EXP
-- -- Set accessory target and effect
-- g_Eq_Accessory_Target = Accessory_Target[g_Eq_Accessory]
-- g_Eq_Accessory_Effect = Accessory_Effect[g_Eq_Accessory]
-- -- Process Battle Message Window
-- if BMessageWindow == 1 then
-- BMWindow()
-- end
end
-- RPG MODULE 2 MAIN BACKGROUND PROCESS --
function rpg2_global_essentials_main(e)
-- At the beginning of a map (if a saved game is not loaded), reset the RPG tables
if g_Flag_Initiate == nil then
-- RPG Module version 2 initiation
RPG2_Initiate()
-- RPG Module version 1 initiation
RPG_Initiate_modified()
else
-- If player has lost a life, reset party HP
if Flag_Continue > g_PlayerLives then
for i = 1,PARTY_SIZE do
if g_CharacterSlot[i] ~= nil and g_CharacterSlot[i] ~= 0 then
g_CharacterHP[g_CharacterSlot[i]] = math.floor(g_CharacterMAXHP[g_CharacterSlot[i]] / 2)
end
end
-- Reset the continue flag
Flag_Continue = g_PlayerLives
end
end
-- RPG Module version 2 background processes
RPG2_Message_Window_Process()
RPG2_Character_Development()
--RPG2_Utility_Items()
RGP2_Equipment()
RPG2_Status()
RPG2_Options()
-- If menu call is possible, process menu
if Flag_MenuCall == 1 then
--RPG2_Menu_Command()
--RPG2_Menu()
end
-- RPG Module version 1 background processes
RPG_Timer_modified()
end
rpg2_battle_special.lua
I was contaced in my Youtube channel about whether it was possible to create a separate battle area outside of the normal field. Of course creating a separate map for this would be impractical, but by playing with TransportToIfUsed() I managed to create something kind like that. This script transfers player and enemy entities to the IfUsed() entity of the enemy character when a battle happens.
However there seems to be some kind bug with a Y coordinate of the enemy entity that causes it to graually sink below ground each time a transfer happens. Not sure whether it is a problem with my script or some GameGuru related issue. However, the script looks like this:
-- LUA Script - precede every function and global member with lowercase name of script + '_main'
-- RPG Module 2 - Turn-based battle : Special battle
--
-- Version 0.9.9 Early Access (17.06.2017)
-- When encountered, this character and player teleport to a special location, where the battle happens.
-- How to use:
-- 1) Create a marker entity with a unique name (e.g. "MARKER1")
-- 2) Set Statics Mode as NO
-- 3) Set Always Active as YES
-- 4) Place the maker on the planned battle area in your map
--
-- 5) Create a character entity
-- 6) Assign this script to the entity
-- 7) Set Static Mode as NO
-- 8) Set Always Active as YES
-- 9) Set If Used as a name of the marker (e.g. "MARKER1")
-- Define flags to communicate with other scripts
FLAG_ENEMY = 1
-- Define tables for entity location
x0 = {}
y0 = {}
z0 = {}
Flag_BattleArena = {}
Flag_Forward = {}
function rpg2_battle_special_init_name(e, name)
-- Get name from GG editor
EntityName[e] = name
-- Define enemy stats
CanEscape[e] = 1
EscapeTimer[e] = 0
EnemyBCommands[e] = {4,4,2,12} -- {1/2 Attack, 1/4 Defence, 1/4 Blunt}
g_EnemyClass[e] = 1
-- Set enemy default statistics
g_EnemyPower[e] = 5
g_EnemyDefence[e] = 2
g_EnemyAgility[e] = 5
g_EnemyAccuracy[e] = 3
g_EnemyWisdom[e] = 2
-- Set enemy equipment
g_EnemyItem[e] = 11 -- Stimulant
g_EnemyWeapon[e] = 9 -- Longsword
g_EnemyArmor[e] = 2 -- Tunic
g_EnemyAccessory[e] = 11 -- Warrior's ring
-- Set animations
ActiveAnimation[e] = 0
-- Set enemy animations
StandStartFrame[e] = 236
StandEndFrame[e] = 265
HurtStartFrame[e] = 236
HurtEndFrame[e] = 236
AttackStartFrame[e] = 160
AttackEndFrame[e] = 189
SpecialStartFrame[e] = 160
SpecialEndFrame[e] = 189
BlockStartFrame[e] = 400
BlockEndFrame[e] = 430
-- Special battle commands
Player_x0 = 0
Player_y0 = 0
Player_z0 = 0
Flag_BattleArena[e] = 0
Flag_Forward[e] = 0
end
function RPG2_Store_Entity_Position(e)
-- Store the entity position to temporary tables
x0[e] = g_Entity[e]['x']
y0[e] = g_Entity[e]['y']
z0[e] = g_Entity[e]['z']
end
function RPG2_Store_Player_Position()
-- Store player position to temporary variables
Player_x0 = g_PlayerPosX
Player_y0 = g_PlayerPosY
Player_z0 = g_PlayerPosZ
end
function RPG2_Return_Player()
-- Return player to the stored position
FreezePlayer()
SetFreezePosition(Player_x0,Player_y0,Player_z0)
UnFreezePlayer()
end
function RPG2_Return_Entity(e)
-- Return entity to the stored position
FreezeAI()
ResetPosition(e,x0[e],y0[e],z0[e])
UnFreezeAI()
end
function RPG2_Move_To_Battle_Arena(e)
-- Store the original positions
RPG2_Store_Player_Position()
RPG2_Store_Entity_Position(e)
-- Move to the new positions
TransportToIfUsed(e)
-- Set the Battle Arena flag
Flag_BattleArena[e] = 1
end
function rpg2_battle_special_main(e)
-- Initiate the Finished flag
if Flag_Finished[e] == nil then
RPG2_Initiate_Enemy(e)
Flag_Finished[e] = 0
end
-- Get Player Distance
PlayerDist = GetPlayerDistance(e)
-- Test whether player is near enough to interact
if PlayerDist < 400 then
RotateToPlayer(e)
end
-- Test whether player is near enough to fight
if Flag_Finished[e] == 0 then
-- If battle is active, activate the battle mode
if Battle_Phase == 0 then
if PlayerDist < 200 then
-- Encounter
RPG2_Enemy_Encounter(e)
end
else
-- Turn player forward
if Battle_Phase > 1 then
if Flag_Forward[e] == 0 then
FreezePlayer()
FreezeAI()
-- Move enemy to the field of vision
ResetPosition(e,g_PlayerPosX,g_PlayerPosY,g_PlayerPosZ + 200)
SetFreezeAngle(10,0,g_PlayerAngZ)
-- UnFreeze/Freeze player to activate the angle
UnFreezePlayer()
UnFreezeAI()
FreezePlayer()
-- Set the flag to prevent multiple cycles
Flag_Forward[e] = 1
end
end
-- If Battle Mode is active
if Flag_Started[e] == 1 then -- This if prevents multiple battles from occuring at the same time
-- Move player and enemy to the battle arena
if Flag_BattleArena[e] == 0 then
RPG2_Move_To_Battle_Arena(e)
else
RPG2_Mode_Battle(1,e)
end
end
end
else
-- Return player and enemy to their original positions
if Flag_BattleArena[e] == 1 then
RPG2_Return_Entity(e)
RPG2_Return_Player()
RPG2_Camera_FixTo(e)
Flag_Forward[e] = 0
-- Reset the Battle Arena flag
Flag_BattleArena[e] = 0
end
if PlayerDist < 200 then
-- First make sure that the player is alive
if g_PlayerHealth > 0 then
-- If battle is "finished", but the enemy still exists, encounter again if escape timer is set to zero
RPG2_Message("You have " .. math.floor((EscapeTimer[e] - g_Time)/1000) .. " seconds to escape!",0,0,0,e)
if EscapeTimer[e] < g_Time then
-- Reset the finished flag
Flag_Finished[e] = 0
-- Reset the escape timer
EscapeTimer[e] = 0
end
else
-- If player has lost, show Game Over
RPG2_Window_Game_Over(e)
end
end
end
--DEBUG STUFF
--Prompt("X: " .. g_PlayerPosX .. " / " .. g_Entity[e]['x'] .. " Y: " .. g_PlayerPosY .. " / " .. g_Entity[e]['y'] .. " Z: " .. g_PlayerPosZ .. " / " .. g_Entity[e]['z'])
end
rpg2_global_essentials.lua (mouse cursor add-on)
Controlling the menu with a mouse cursor has been repeatedly requested, so I've now written a simple function to make it happen, even though I have to point out that I'm not 100 % satisfied of the mouse cursor behaviour in GG games. If you have knowledge of Lua and want to use the mouse cursor, take this function, add it to the code and call it from different menu functions to activate the mouse cursor. If not, don't worry. I'm going to include this to the next update.
function RPG2_Control_MouseCursor(ox,oy,ex,ey,NumColumns,ListSize)
-- This function draws the cursor and reads its position
SetSpritePosition(SprCursor,g_MouseX,g_MouseY)
SetSpriteDepth(SprCursor,0)
-- Check the position of the cursor
if g_MouseX >= ox and g_MouseX <= ex and g_MouseY >= oy and g_MouseY <= ey then -- IF mouse cursor is on the area
-- Define local variables for mouse coordinates
local CursorLX = math.ceil((g_MouseX - ox) / (ex - ox) * NumColumns)
local CursorLY = math.floor((g_MouseY - oy) / (ey - oy) * ListSize/NumColumns)
-- Set the menu command according to mouse cursor position
ActiveCommand[ActiveMenu] = CursorLX + (CursorLY * NumColumns)
else
-- If the mouse cursor is outside the area, set 1 as active
ActiveCommand[ActiveMenu] = 1
end
-- Prevent too high selection
if ActiveCommand[ActiveMenu] > ListSize then
ActiveCommand[ActiveMenu] = 1
end
end
This is how it looks like:
https://youtu.be/icn3gpEgidM