E
Exlo
Guest
This will be my first post here so, first of all, hello and thanks for taking the time to read about my problem. I'm really sorry if it's a bit of a read.
I'm very new to GMS and coding in general, so I've of course jumped straight into something way out of my league by trying to create a turn based RPG. I've learned a lot over the course of these 2 months and truly believe I can do it, but there must be something fundamental I'm misunderstanding here. This is my third crack at this, and keep in mind I'm likely dreadfully disorganized and probably have some terrible habits code-wise. Any tips to remedy these issues are more than welcome. I will try to explain the system as concisely as possible, but keep in mind I've never really asked for help yet, so I'm new even to this. I'm willing to share the project file if necessary. The exact nature of the issue is that characters don't seem to even do anything on the combat screen, though I think I've finally figured out how to reference all the data and use all the structures provided properly. However, if anyone can clearly explain accessors in the context I am using them, it would be much appreciated. I think I understand them finally but when I would see examples of use it had me confused more often than not.
So first player character data objects are created in the start menu, and put into an object that will later be manipulated to manage inventories and possible party members. Right now I'm just filling the variables with unique instance IDs on creation of those party members, and it's literally just an object with three vars. Ally1, ally2, ally3. Each character data object is persistent and looks like this.
Enemy objects are exactly the same. Basically, we step on a tile to start an encounter, that tile passes an encounter script to another persistent object, and then the room changes to rm_Combat. Now the combat manager is made. This object should be handling everything that's going on in the scene, and it is created before anything else in the room.
Here is the create event.
And here is the step event.
Now I'll show you the scripts I'm using in the thing. This is where I think I'm having issues, most likely in calculating the turn order but I just can't be sure if my method isn't working or what. The encounter script just places enemy instances (using instance create layer) in positions with objects returning their IDs to the party_array on collision.
Here's calculate_turn_order.
In the step event, here is the enemy ai script deciding the action script.
And here are our action scripts. Attack.
And defend (much more complex due to me trying to set up this modifier system).
I'm sorry this is so much to look at. I've just gotten so frustrated trying to figure all of this out and want to so bad, especially considering once I'm over this hump a lot of the other systems won't even be this complex -- or they won't need to be anyway. I've been over it so many times and can't figure out where things aren't clicking.
Keep in mind my code isn't throwing errors, I just know the enemies aren't dealing damage to the player party. Enemy strength is higher than all the player parties endurance so I should be seeing something happen. I'm tracking the health right know with just simple objs drawing text. I guess I'll post one of those too.
I know it references the data properly because the correct numbers appear when combat starts. Anyway, thank you for taking the time to read that. I really really appreciate any help or guidance. Ask me anything if you think I've left something out.
I'm very new to GMS and coding in general, so I've of course jumped straight into something way out of my league by trying to create a turn based RPG. I've learned a lot over the course of these 2 months and truly believe I can do it, but there must be something fundamental I'm misunderstanding here. This is my third crack at this, and keep in mind I'm likely dreadfully disorganized and probably have some terrible habits code-wise. Any tips to remedy these issues are more than welcome. I will try to explain the system as concisely as possible, but keep in mind I've never really asked for help yet, so I'm new even to this. I'm willing to share the project file if necessary. The exact nature of the issue is that characters don't seem to even do anything on the combat screen, though I think I've finally figured out how to reference all the data and use all the structures provided properly. However, if anyone can clearly explain accessors in the context I am using them, it would be much appreciated. I think I understand them finally but when I would see examples of use it had me confused more often than not.
So first player character data objects are created in the start menu, and put into an object that will later be manipulated to manage inventories and possible party members. Right now I'm just filling the variables with unique instance IDs on creation of those party members, and it's literally just an object with three vars. Ally1, ally2, ally3. Each character data object is persistent and looks like this.
Code:
// PORTRAIT
portrait = spr_player_portrait;
// STATS
av_experience = 0;
av_max_health = 100;
av_current_health = 100;
av_max_mana = 25;
av_current_mana = 25;
av_max_stamina = 25;
av_current_stamina = 25;
av_max_strength = 5;
av_current_strength = 5;
av_max_endurance = 5;
av_current_endurance = 5;
av_max_intelligence = 5;
av_current_intelligence = 5;
av_max_wisdom = 5;
av_current_wisdom = 5;
av_max_agility = 10;
av_current_agility = 10;
av_max_ego = 5;
av_current_ego = 5;
av_max_piety = 5;
av_current_piety = 5;
av_max_luck = 3;
av_current_luck = 3;
av_max_accuracy = 0.5;
av_current_accuracy = 0.5;
av_max_evasion = 0.1;
av_current_evasion = 0.1;
// MODIFIERS
//Modifier remove scripts stored here (cycle array, if != undefined decrement that mods round count, then check if 0)
mod_is_applied = array_create(mod_types.length, undefined);
//Modifier count (if zero: remove flag and effect on new round, if other: subtract by 1)
mod_round_count = array_create(mod_types.length, 0);
//Holds values saved by mod skills to refer to on removal
mod_magnitudes = ds_grid_create(mod_types.length, effect_types.length);
//Actual mod values
av_experience_mod = 0;
av_health_mod = 0;
av_mana_mod = 0;
av_stamina_mod = 0;
av_strength_mod = 0;
av_endurance_mod = 0;
av_intelligence_mod = 0;
av_wisdom_mod = 0;
av_agility_mod = 0;
av_ego_mod = 0;
av_piety_mod = 0;
av_luck_mod = 0;
av_accuracy_mod = 0;
av_evasion_mod = 0;
//Go ahead and add the player to position one in list manager
obj_player_list_manager.ally1 = id;
Here is the create event.
Code:
//Disallow player input until player turn
global.p_combat_input = false;
//Hold encounter script
encounter_scr = obj_encounter_manager.script;
//Hold current action to execute
current_action = undefined;
//Hold character currently inputting action
current_actor = undefined;
//Hold current target for actions
current_target = undefined;
//Hold number of rounds passed this combat
current_round = 0;
//Hold current member of combat having mods checked
mod_cleanup_target = undefined;
//Party array
//0-2 are ally
//3-8 are enemy
party_array = array_create(9, undefined);
party_array[0] = obj_player_list_manager.ally1;
party_array[1] = obj_player_list_manager.ally2;
party_array[2] = obj_player_list_manager.ally3;
//Set up enemies in scene and in party_array
script_execute(encounter_scr);
//Holds list of characters in combat ordered by agi
turn_order = array_create(9, undefined);
//Used to read positions of turn_order and return current actor
turn_pos = 0;
//Calculate the turn order
calculate_turn_order();
//Initiate new round
new_round = true;
Code:
if (new_round)
{
//Cycle through mods and remove them if round count is 0
for (var _ii = 0; _ii < 9; _ii += 1)
{
mod_cleanup_target = turn_order[_ii];
if (mod_cleanup_target != undefined)
{
//Cycle through THAT ACTORS mods
for (var _jj = 0; _jj < mod_types.length; _jj += 1)
{
//If mod IS applied
if(mod_cleanup_target.mod_is_applied[_jj] != undefined)
{
//Remove a round from that mods round count
mod_cleanup_target.mod_round_count[@ _jj] -= 1;
//If that mods round count = 0, execute the script in mod_cleanup_target.mod_is_applied
if (mod_cleanup_target.mod_round_count[_jj] == 0)
{script_execute(mod_cleanup_target.mod_is_applied[_jj]);}
}
}
}
}
current_round += 1;
turn_pos = 0;
new_round = false;
}
//First check if turn order position is undefined, if it is we just go ahead and increment pos
if (turn_order[turn_pos] != undefined)
{
//Check if it's enemy or player turn
if (turn_order[turn_pos] == party_array[0] || party_array[1] || party_array[2])
{
//Set current actor to member of player party
current_actor = turn_order[turn_pos];
//On player turn first allow player input (set this to false in skill scripts)
global.p_combat_input = true;
//If current action is filled we will execute its contents
if (current_action != undefined)
script_execute(current_action);
//Reset current action
current_action = undefined;
}
else
{
//Reset current target here to help AI
current_target = undefined;
//Set current actor to member of enemy party
current_actor = turn_order[turn_pos];
//If its an enemy's turn we will need to have their ai_package determine a target and actions
script_execute(turn_order[turn_pos].ai_package);
//Execute action
script_execute(current_action);
//Reset current action
current_action = undefined;
}
}
else
turn_pos += 1;
//If we have incremented to the total number of possible characters, start new round
if (turn_pos == 8)
new_round = true;
Here's calculate_turn_order.
Code:
//Clear original turn_order array
for (var _j = 0; _j < 9; _j += 1)
{
turn_order[@ _j] = undefined;
}
//Create grid to hold references and their agi
var _order_grid = ds_grid_create(9, 2);
ds_grid_clear(_order_grid, -1);
//Fill grid
var _char = undefined;
if (party_array[0] != undefined){
_char = party_array[@ 0];
_order_grid[# 0, 0] = _char;
_order_grid[# 0, 1] = _char.av_current_agility;
}
if (party_array[1] != undefined){
_char = party_array[@ 1];
_order_grid[# 1, 0] = _char;
_order_grid[# 1, 1] = _char.av_current_agility;
}
if (party_array[2] != undefined){
_char = party_array[@ 2];
_order_grid[# 2, 0] = _char;
_order_grid[# 2, 1] = _char.av_current_agility;
}
if (party_array[3] != undefined){
_char = party_array[@ 3];
_order_grid[# 3, 0] = _char;
_order_grid[# 3, 1] = _char.av_current_agility;
}
if (party_array[4] != undefined){
_char = party_array[@ 4];
_order_grid[# 4, 0] = _char;
_order_grid[# 4, 1] = _char.av_current_agility;
}
if (party_array[5] != undefined){
_char = party_array[@ 5];
_order_grid[# 5, 0] = _char;
_order_grid[# 5, 1] = _char.av_current_agility;
}
if (party_array[6] != undefined){
_char = party_array[@ 6];
_order_grid[# 6, 0] = _char;
_order_grid[# 6, 1] = _char.av_current_agility;
}
if (party_array[7] != undefined){
_char = party_array[@ 7];
_order_grid[# 7, 0] = _char;
_order_grid[# 7, 1] = _char.av_current_agility;
}
if (party_array[8] != undefined){
_char = party_array[@ 8];
_order_grid[# 8, 0] = _char;
_order_grid[# 8, 1] = _char.av_current_agility;
}
for (var _i = 0; _i < 9; _i += 1){
//Find greatest agility value
var _max_agi = ds_grid_get_max(_order_grid, 0, 1, 8, 1);
//Find x position of the greatest agility value
var _max_agi_x = ds_grid_value_x(_order_grid, 0, 1, 8, 8, _max_agi);
//Send that reference from the grid to the front of the turn order
turn_order[@ _i] = _order_grid[# _max_agi_x, 0];
//Set that reference's agi to -1 and search again
_order_grid[# _max_agi_x, _max_agi] = -1;
}
//Clean up grid
ds_grid_destroy(_order_grid);
Code:
//When choosing target remember 0-2 is player party and 3-8 is enemy
while (current_target == undefined)
current_target = party_array[@ irandom(3)];
//If target is player party
if (current_target == party_array[@ 0] || party_array[@ 1] || party_array[@ 2])
{
current_action = basic_action_attack;
}
else
current_action = basic_action_defend;
Code:
//Calculate base damage
var _base = current_target.av_current_endurance - current_actor.av_current_strength;
current_target.av_current_health += _base;
//End skill
global.p_combat_input = false;
turn_pos += 1;
Code:
//Calculate base effect magnitude
var _end_base = current_actor.av_current_endurance * 2;
var _wis_base = current_actor.av_current_wisdom * 2;
//Add this to appropriate values
current_actor.av_endurance_mod += _end_base;
current_actor.av_current_endurance += _end_base;
current_actor.av_wisdom_mod += _wis_base;
current_actor.av_current_wisdom += _wis_base;
//Now add this to the magnitude grid for the current actor (this is checked so we know what values to remove
//on remove_mod_defend, in this case)
current_actor.mod_magnitudes[# mod_types.defend, effect_types.endurance] = _end_base;
current_actor.mod_magnitudes[# mod_types.defend, effect_types.wisdom] = _wis_base;
//Add mod info to current_actor
current_actor.mod_is_applied[@ mod_types.defend] = remove_mod_defend;
current_actor.mod_round_count[@ mod_types.defend] = 1;
//End skill
global.p_combat_input = false;
turn_pos += 1;
Keep in mind my code isn't throwing errors, I just know the enemies aren't dealing damage to the player party. Enemy strength is higher than all the player parties endurance so I should be seeing something happen. I'm tracking the health right know with just simple objs drawing text. I guess I'll post one of those too.
Code:
draw_self();
var _owner = obj_player_list_manager.ally1;
var _max = _owner.av_max_health + _owner.av_health_mod;
var _current = _owner.av_current_health;
draw_text(x + (bar_width / 2), y + (bar_height / 2), string(_current) + "/" + string(_current));