edit by scorpiorus (02.09.2009):
Here is an AGS 3.1.2 SP1 - compatible version of the QFG1-style battle template:
http://www.geocities.com/scorpiorus82/qfg_battle/qfg_battle_v12.zip
I already sent a PM to Scopiorus about this. But didn't think I was descriptive enough about the problem or he may be too busy or gone being it has been so long. Plus I don't know if this is the right place for this but...
I used an old template for a Quest For Glory battle sytem in an older version of AGS and updated it to AGS 3.1.2-SP1 and can't get the status bar to appear in the background.
This is my script after trying to edit it myself it is from a room script
function RawDrawBar(int x1, int y1, int x2, int y2, int col) {
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.Clear(14);
surface.DrawingColor = 13;
DrawingSurface.DrawTriangle(x1, y1, x2, y1, x2, y2);
DrawingSurface.DrawTriangle(x1, y1, x2, y2, x1, y2);
surface.Release();
}
This is the error I got from this code
room3.asc(412): Error (line 412): must have an instance of the struct to access a non-static member
And this is the original script that Scopiorus wrote when he made it
function RawDrawBar(int x1, int y1, int x2, int y2, int col) {
RawSetColor(col);
RawDrawTriangle(x1, y1, x2, y1, x2, y2);
RawDrawTriangle(x1, y1, x2, y2, x1, y2);
}
Tis is my error message from using this code
Failed to save room room3.crm; details below
room3.asc(409): Error (line 409): Undefined token 'RawSetColor'
Thank you in advance to anyone that helps and if this is in the wrong place I'm very sorry.
Try this (not tested):
...
surface.DrawTriangle(x1, y1, x2, y1, x2, y2);
surface.DrawTriangle(x1, y1, x2, y2, x1, y2);
surface.Release();
}
Thank you the game loads now but I'm getting a yellow background with this code
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.Clear(14);
surface.DrawingColor = 13;
surface.DrawTriangle(x1, y1, x2, y1, x2, y2);
surface.DrawTriangle(x1, y1, x2, y2, x1, y2);
surface.Release();
And only one meter (HP and SP) is working if you need to know it is the bottom right meter (enemy SP) and it don't work right.
I found that if I put this code
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = 13;
surface.DrawTriangle(x1, y1, x2, y1, x2, y2);
surface.DrawTriangle(x1, y1, x2, y2, x1, y2);
surface.Release();
It shows all the meters but they stay full and don't decrease when character is damaged. Again thank you for any help in advance.
If this is the only code, then all it does is draw two filled rectangles. There should be more code, some that employs the health variables in the drawing commands.
Quote from: seraphimdreamer777 on Thu 23/07/2009 08:51:04
Thank you the game loads now but I'm getting a yellow background with this code
But that's exactly what the line "surface.Clear(14);" does. What do you actually want to do (or, what the template should actually be doing)? If you don't want the screen to be cleared just remove or comment this line. If it's supposed to be a temporal screen for displaying the stats there ought to be some other functions that restore the original background when it's done. But I think what you want to do is the former, so just remove this line.
Also, I just noticed the two DrawTriangle() codes are used to draw a rectangular bar. You can just use a single line "surface.DrawRectangle(x1,y1,x2,y2);". I'm not quite sure, but seems that the template was originally written for a very old version of AGS which didn't have the rectangle drawing function yet.
The reason the bar doesn't decrease is because you just draw a rectangle on top of the old one. You need to clear the old one with another rectangle with black (or any background colour of your choice) before drawing the updated one on top of it.
Since I don't know what that template actually does and I have no intention to really look into it I may not of much help, maybe some other people can answer in greater detail.
I'm just updating this code here so in case anyone can help me further or if anyone may want to use it themselves to learn a little more about designing a battle mode in AGS 3.1.2-SP1 once I solve the final problem with it Which is the Player/Enemy life bars don't decrease to zero by battles end. Leaving a little bit of life in the meter. And I get permission from Scorpiorus I will make an updated template for this in the modules plugin template section of the forum.
//****************************************************************************************
//* Name : QFG-style Battle System
//* Version: 1.1 (updated to work with AGS v2.72)
//* Author : Scorpiorus
//*
//* Notes : Graphic materials were ripped from the Quest for Glory (VGA) game by Sierra
//* just to demonstrate the battle working. You must replace them with your own
//* ones so not to violate the copyright law!
//****************************************************************************************
//
//
//==================================================================================//
// ACTIONS DEFINITIONS: //
//==================================================================================//
//
// Defines a maximum number of actions (default is 30)
#define ACTIONS_MAX 30
//==========================
// Adding new actions:
//==========================
//
// To add a new action define its name and assign a certain index.
// WARNING: Each action must have its own unique index!
//
// Example: #define ACTION_THROW_DAGGER 6
//
//
//---------------------------------------------------
// Action Name Action Index
//---------------------------------------------------
#define ACTION_NEUTRAL 0
#define ACTION_PARRY 1
#define ACTION_DODGE 2
#define ACTION_ATTACK1 3
#define ACTION_ATTACK2 4
#define ACTION_RETREAT 5
// <-- add new actions here
//--------------------------------------------------
//=======================================================================================
// BATTLE ENGINE IMPLEMENTATION
//=======================================================================================
//
//--------------------------- FIGHTING CASTES DATABASE ----------------------------------
struct Tfighter {
int action_is_set [ACTIONS_MAX]; // is action available
int action_view [ACTIONS_MAX]; // action view
int action_loop [ACTIONS_MAX]; // action loop
int action_active_frame [ACTIONS_MAX]; // start moment of the active phase
int action_duration [ACTIONS_MAX]; // duration (in frames) of the active phase
int action_speed [ACTIONS_MAX]; // action animating speed
int action_energy [ACTIONS_MAX]; // max energy required to perform an action
int position_x;
int position_y;
};
// maximum fighting castes (can be increased later):
#define FIGHTERS_MAX 20
// an array storing all of the fighting castes:
Tfighter fighter [FIGHTERS_MAX];
function AdjustValue(int value, int min, int max) {
if (value < min) return min;
else if (value > max) return max;
else return value;
}
// checks if the value is valid and displays a error if it's not:
function CheckValue(int value, int min, int max) {
if (value < min || value > max) {
Display ("Battle system error: invalid value specified!");
QuitGame(0);
}
else return value;
}
function ActionProps( int caste,
int action,
int speed,
int view,
int loop,
int active_frame,
int duration,
int energy ) {
caste = CheckValue(caste, 0, FIGHTERS_MAX-0);
action = CheckValue(action, 0, ACTIONS_MAX-1);
fighter[caste].action_speed [action] = speed;
fighter[caste].action_view [action] = AdjustValue(view, 1, 300);
fighter[caste].action_loop [action] = loop;
fighter[caste].action_active_frame [action] = AdjustValue(active_frame, 0, 100); // 100 = temp value
fighter[caste].action_duration [action] = AdjustValue(duration, 0, 100); // 100 = temp value
fighter[caste].action_energy [action] = AdjustValue(energy, 0, 1000); // 1000 = temp value
fighter[caste].action_is_set [action] = 1;
}
#define Positioning Cast_SetDefaultPosition
function Cast_SetDefaultPosition(int caste, int x, int y) {
caste = CheckValue(caste, 0, FIGHTERS_MAX-1);
fighter[caste].position_x = x;
fighter[caste].position_y = y;
}
function GetActionSpeed (int caste, int action) { return fighter[caste].action_speed[action]; }
function GetActionView (int caste, int action) { return fighter[caste].action_view[action]; }
function GetActionLoop (int caste, int action) { return fighter[caste].action_loop[action]; }
function GetActiveFrame (int caste, int action) { return fighter[caste].action_active_frame[action]; }
function GetStopActive (int caste, int action) {
return fighter[caste].action_active_frame[action] +
fighter[caste].action_duration[action];
}
function GetActionEnergy(int caste, int action) { return fighter[caste].action_energy[action]; }
function IsActionAssigned(int caste, int action) { return fighter[caste].action_is_set[action]; }
function Caste_GetX(int caste) { return fighter[caste].position_x; }
function Caste_GetY(int caste) { return fighter[caste].position_y; }
//===================== END OF FIGHTING CASTES DATABASE ============================//
int Health_Max = 100;
int Stamina_Max = 100;
int Strength_Max = 100;
int Weapon_use_Max = 100;
function FightersProps( int health_max,
int stamina_max,
int strength_max,
int weapon_use_max ) {
Health_Max = health_max;
Stamina_Max = stamina_max;
Strength_Max = strength_max;
Weapon_use_Max = weapon_use_max;
}
// Fight-scene Objects:
// ========= name: ======= num ==
#define PLAYER1 0
#define PLAYER2 1
#define STATUS_PLAYER1 2
#define STATUS_PLAYER2 3
// Colours:
#define COLOR_BLACK 0
#define COLOR_LIGHTRED 12
struct TPlayer {
int keys[ACTIONS_MAX]; // keyboard control
int key_hold;
int type; // CPU or HUMAN
int caste; // goblin, hero fighter, etc...
int order; // action to perform
int action; // current action
int action_timer; // action timer
int force_action; // finish current action and force new one
int health; // health
int stamina; // stamina
int strength; // strength
int weapon_use; // weapon use skill
// Animation variables:
//----------------------------------------
int is_animating; // is animating?
int view; // current view
int loop; // current loop
int frame; // current frame
int speed; // animation speed
int timer; // animation timer
//----------------------------------------
};
#define PLAYERS_MAX 2
//player types:
//------ name -- num --
#define CPU 0
#define HUMAN 1
TPlayer Player[PLAYERS_MAX];
int HumanPlayer = PLAYER1; //debug purposes
function GetPlayerType (int plr) { return Player[plr].type; }
function GetPlayerCaste (int plr) { return Player[plr].caste; }
function GetPlayerAction (int plr) { return Player[plr].action; }
function GetPlayerHealth (int plr) { return Player[plr].health; }
function GetPlayerStamina (int plr) { return Player[plr].stamina; }
function GetPlayerStrength (int plr) { return Player[plr].strength; }
function GetPlayerWeaponUse(int plr) { return Player[plr].weapon_use;}
function SetPlayerHealth (int plr, int health) {
Player[plr].health = AdjustValue(health, 0, Health_Max);
}
function SetPlayerStamina (int plr, int stamina) {
Player[plr].stamina = AdjustValue (stamina, 0, Stamina_Max);
}
function StopAction (int plr) { Player[plr].action = ACTION_NEUTRAL; }
function SetPlayerPosition(int plr, int x, int y) {
object[plr].SetPosition(x, y);
}
function IsActionActive(int plr, int action) {
int cur_frame = Player[plr].frame;
int caste = Player[plr].caste;
int start_frame = GetActiveFrame(caste, action);
int stop_frame = GetStopActive (caste, action);
return cur_frame >= start_frame &&
cur_frame < stop_frame &&
Player[plr].action == action &&
Player[plr].is_animating == 1;
}
function SetPlayerDefaultPosition(int plr) {
#define PLAYER1_DEFAULT_POSITION 81, 167
#define PLAYER2_DEFAULT_POSITION 117, 136
if (plr == PLAYER1) SetPlayerPosition(plr, PLAYER1_DEFAULT_POSITION);
else if (plr == PLAYER2) SetPlayerPosition(plr, PLAYER2_DEFAULT_POSITION);
}
function AssignPlayer( int plr,
int caste,
int health,
int stamina,
int strength,
int weapon_use ) {
Player[plr].caste = AdjustValue (caste, 0, FIGHTERS_MAX - 1);
Player[plr].health = AdjustValue (health, 1, Health_Max);
Player[plr].stamina = AdjustValue (stamina, 1, Stamina_Max);
Player[plr].strength = AdjustValue (strength, 0, Strength_Max);
Player[plr].weapon_use = AdjustValue (weapon_use, 0, Weapon_use_Max);
SetPlayerDefaultPosition(plr); // set default position
// now try to set specific position (if available):
int plr_x = Caste_GetX(caste);
int plr_y = Caste_GetY(caste);
if (plr_x > 0 && plr_y > 0) SetPlayerPosition(plr, plr_x, plr_y);
}
//==================================== PLAYER ANIMATION ENGINE ====================================
function AnimatePlayer (int plr, int view, int loop, int speed) {
Player[plr].view = view; // set view
Player[plr].loop = loop; // set loop
Player[plr].speed = speed; // set speed
Player[plr].timer = 0; // reset timer;
Player[plr].frame = -1;
Player[plr].is_animating = 1;
}
function IsPlayerAnimating (int plr) { return Player[plr].is_animating; }
function AnimatePlayer_Runtime(int plr) {
if (Player[plr].is_animating == 1) {
Player[plr].timer --;
if (Player[plr].timer < 0) {
int frames_num = Game.GetFrameCountForLoop(Player[plr].view, Player[plr].loop);
// if there is no more frames in loop then return (run next loop is not supported!)
if (Player[plr].frame == frames_num - 1) {Player[plr].is_animating = 0; return 1; }
Player[plr].frame += 1;
object[plr].SetView(Player[plr].view, Player[plr].loop, Player[plr].frame);
ViewFrame * viewframe = Game.GetViewFrame(Player[plr].view, Player[plr].loop, Player[plr].frame);
Player[plr].timer = Player[plr].speed + viewframe.Speed;
}
}
}
//=================================================================================================
function DoAction(int plr, int action) {
int caste = GetPlayerCaste(plr);
if (IsActionAssigned(caste, action) == 1)
if (Player[plr].force_action == 0) Player[plr].order = action;
}
function ForceAction(int plr, int action) {
int caste = GetPlayerCaste(plr);
if (IsActionAssigned(caste, action) == 1) {
DoAction(plr, action);
Player[plr].force_action = 1;
}
}
function GetEnergy(int plr) {
int action = GetPlayerAction(plr);
int caste = GetPlayerCaste(plr);
return GetActionEnergy(caste, action);
}
#define IsAction IsActionActive
//######################################################################################
//######################### ON ACTION EVENT FUNCTIONS: #################################
//
// Fight logic is described with these two event-handling function!
function ON_ACTION_START (int A) {
// triggered when attacker (A) has started performing an action (frame == 0)
// (not necessarily in an active phase)
int energy = GetEnergy(A);
int new_stamina = GetPlayerStamina(A) - Random(energy);
SetPlayerStamina(A, new_stamina);
}
function ON_ACTION_ACTIVE (int A, int B) {
// triggered when attacker's (A) action goes into the active phase (frame == active_frame)
// defender's (B) active action can be checked to possibly block the attacker
//
// Note: this function called for each of the fighters, provided one is attacking
// so A may represent a GOBLIN and B - a FIGHTER,
// or B is GOBLIN and A is FIGHTER,
// depending on who is attacking now!
//
// if A attacks (active phase)
if ( IsAction(A, ACTION_ATTACK1) || IsAction(A, ACTION_ATTACK2 ) ) {
// if B is not defending (or maybe performing, but not in active phase)
if ( IsAction(B, ACTION_PARRY) == 0 && IsAction(B, ACTION_DODGE) == 0 ) {
// if attacker has enough weapon_use skill and some luck
if (GetPlayerWeaponUse(A) - Random(Weapon_use_Max) >= 0) {
// ...and has enough stamina
if (GetPlayerStamina(A) > 0) {
// then hit defender
int health_after_hit = GetPlayerHealth(B) - GetPlayerStrength(A);
SetPlayerHealth(B, health_after_hit);
ForceAction(B, ACTION_RETREAT); // forces defender to back off
StopAction(A); // stop active phase (so the attacker won't hit the defender repeatedly!)
}
}
// winning conditions
// (you can put a code to set up some global variable to indicate who wins
// and exit the room here)
while (GetPlayerHealth(B) <= 0) {
Display("Player %d wins!", A + 1);
QuitGame(1);
}
}
}
}
//######################################################################################
//######################################################################################
function RawDrawBar(int x1, int y1, int x2, int y2, int col) {
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = 0;
surface.DrawRectangle(x1,y1,x2,y2);
surface.DrawingColor=col;
surface.DrawRectangle(x1,y1,x2,y2);
surface.Release();
}
function DrawPercentBar(int x, int y, int width, int length, int col, int percent) {
percent = AdjustValue(percent, 0, 100);
int colored_length = (length * percent) / 100;
RawDrawBar(x, y, x+length, y+width, COLOR_BLACK);
if (percent > 0) RawDrawBar(x, y, x+colored_length, y+width, col);
}
function ProcessControl_CPU(int plr) {
// AI: (a dummy one! :))
int random_action = Random(ACTIONS_MAX-1);
if (random_action != ACTION_RETREAT) DoAction(plr, random_action);
}
function GetActionOnPressedKey(int plr) {
int i;
while (i<ACTIONS_MAX) {
if (IsKeyPressed(Player[plr].keys)) return Player[plr].keys;
i++;
}
return -1;
}
function SetKey(int plr, int action, int keycode) {
Player[plr].keys[action] = keycode;
}
function ProcessControl_Human(int plr) {
int i=0;
int pressed_key=-1;
int action=-1;
while (i < ACTIONS_MAX) {
if (IsKeyPressed(Player[plr].keys)) {
pressed_key = Player[plr].keys;
action = i;
i = ACTIONS_MAX - 1; // <- exit loop
}
i++;
}
if (action != -1 && Player[plr].key_hold == 0) {
DoAction(plr, action);
}
if (pressed_key != -1) Player[plr].key_hold = 1;
else Player[plr].key_hold = 0;
}
function ProcessAction(int id) {
if (IsPlayerAnimating(id) == 0 || Player[id].force_action == 1) {
Player[id].force_action = 0; //reset
Player[id].action = Player[id].order;
Player[id].order = ACTION_NEUTRAL;
int action = Player[id].action;
int caste = Player[id].caste;
int view = GetActionView(caste, action);
int loop = GetActionLoop(caste, action);
int speed = GetActionSpeed(caste, action);
int frame = 0;
int repeat = 0;
AnimatePlayer (id, view, loop, speed);
Player[id].action_timer = 0;
ON_ACTION_START(id);
}
Player[id].action_timer++;
}
function ProcessPlayers() {
if (IsGamePaused() == 0) {
int plr = 0;
while (plr < PLAYERS_MAX) {
if (Player[plr].type == CPU) ProcessControl_CPU(plr);
else if (Player[plr].type == HUMAN) ProcessControl_Human(plr);
ProcessAction(plr);
AnimatePlayer_Runtime(plr); // animate player
int opponent = 0;
while (opponent < PLAYERS_MAX) {
int action = Player[plr].action;
if ( IsActionActive(plr, action) && plr != opponent )
ON_ACTION_ACTIVE(plr, opponent);
opponent++;
}
plr++;
}
}
}
function DisplayPlayerStatus(int plr, int status_obj) {
int per_health = Player[plr].health * 100 / Health_Max;
int per_stamina = Player[plr].stamina * 100 / Stamina_Max;
int x0 = object[status_obj].X + 26;
int y0 = object[status_obj].Y - 24;
DrawPercentBar(x0, y0, 9, 47, COLOR_LIGHTRED, per_health);
DrawPercentBar(x0, y0+11, 9, 47, COLOR_LIGHTRED, per_stamina);
}
function DrawStatusBars() {
DisplayPlayerStatus(PLAYER1, STATUS_PLAYER1);
DisplayPlayerStatus(PLAYER2, STATUS_PLAYER2);
}
#sectionstart room_a // DO NOT EDIT OR REMOVE THIS LINE
function room_a() {
// script for room: Repeatedly execute
//****** BATTLE ENGINE's MAIN LOOP: ************************
ProcessPlayers(); // players main loop
DrawStatusBars(); // players status info
}
#sectionend room_a // DO NOT EDIT OR REMOVE THIS LINE
function EnableStatusGUI(int plr) {
if (plr == PLAYER1) object[STATUS_PLAYER1].Visible = true;
else if (plr == PLAYER2) object[STATUS_PLAYER2].Visible = true;
}
function SetHumanPlayer(int plr) {
HumanPlayer = plr; // debug variable
Player[plr].type = HUMAN;
}
#sectionstart room_c // DO NOT EDIT OR REMOVE THIS LINE
function room_c() {
// script for Room: Player enters room (before fadein)
//=======================================================
// Battle's General Settings:
//=======================================================
//
//======================================================
// Fighting castes
//======================================================
//---------- Caste Name:---- Caste Index ----
#define HERO_FIGHTER 0
#define GOBLIN 1
// Creating castes:
// Frame - first active frame in a loop
// Dur - the number of active frames in a loop (determines when action is active)
// En - the energy required to perform an action
//------------ Caste name ----- Action ---- Spd - View - Loop - Frame - Dur - En --
// FIGHTER:
ActionProps(HERO_FIGHTER, ACTION_NEUTRAL, 7, 2, 0, 0, 0, 0 );
ActionProps(HERO_FIGHTER, ACTION_ATTACK1, 7, 2, 1, 1, 1, 3 );
ActionProps(HERO_FIGHTER, ACTION_ATTACK2, 6, 2, 2, 1, 1, 5 );
ActionProps(HERO_FIGHTER, ACTION_PARRY, 7, 2, 3, 0, 3, 2 );
ActionProps(HERO_FIGHTER, ACTION_DODGE, 7, 2, 4, 0, 2, 1 );
ActionProps(HERO_FIGHTER, ACTION_RETREAT, 7, 2, 5, 0, 0, 0 );
// GOBLIN:
ActionProps(GOBLIN, ACTION_NEUTRAL, 7, 3, 0, 0, 0, 0 );
ActionProps(GOBLIN, ACTION_ATTACK1, 7, 3, 1, 1, 1, 3 );
ActionProps(GOBLIN, ACTION_ATTACK2, 7, 3, 2, 3, 1, 5 );
ActionProps(GOBLIN, ACTION_PARRY, 7, 3, 3, 0, 2, 2 );
ActionProps(GOBLIN, ACTION_DODGE, 7, 3, 4, 0, 2, 1 );
ActionProps(GOBLIN, ACTION_RETREAT, 7, 3, 5, 0, 0, 0 );
//---------------------------------------------------------------------------------
//-------------- Health Max - Stamina Max - Strength Max - Weapon use Max --
FightersProps( 100, 100, 100, 100 );
EnableStatusGUI(PLAYER1); // show status GUI
EnableStatusGUI(PLAYER2); // show status GUI
/*
======================================================
Player settings (before fight starts):
====================================================== */
// Keycodes (SEE ASCII Table for more info:)
#define KEY_UP 372
#define KEY_DOWN 380
#define KEY_LEFT 375
#define KEY_RIGHT 377
#define KEY_W 87
#define KEY_S 83
#define KEY_A 65
#define KEY_D 68
// Setting keyboard control:
// PLAYER 1:
//-----player---- action ------ keycode -----
SetKey(PLAYER1, ACTION_ATTACK1, KEY_UP );
SetKey(PLAYER1, ACTION_ATTACK2, KEY_LEFT );
SetKey(PLAYER1, ACTION_PARRY, KEY_DOWN );
SetKey(PLAYER1, ACTION_DODGE, KEY_RIGHT);
// PLAYER 2:
SetKey(PLAYER2, ACTION_ATTACK1, KEY_W);
SetKey(PLAYER2, ACTION_ATTACK2, KEY_A);
SetKey(PLAYER2, ACTION_PARRY, KEY_S);
SetKey(PLAYER2, ACTION_DODGE, KEY_D);
//------------ Player --- Caste ----- Health - Stamina -- Strength - Weapon use -
AssignPlayer(PLAYER1, HERO_FIGHTER, 100, 100, 6, 100 );
AssignPlayer(PLAYER2, GOBLIN, 100, 100, 5, 100 );
// comment-out both for a CPU vs. CPU fight
// uncomment both for a HUMAN vs. HUMAN fight
//
SetHumanPlayer(PLAYER1); // set human player
//SetHumanPlayer(PLAYER2); // set human player
}
#sectionend room_c // DO NOT EDIT OR REMOVE THIS LINE
So, what else do you you want help of? Or, what is not working now? Please be more specific, so we can look into the codes with a target in mind.
Edited: Okay, I'd tried to have a look, try to see whether this quick (unverified) edit helps:
function RawDrawBar(int x1, int y1, int x2, int y2, int col) {
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = col; // <-- Just change this
surface.DrawRectangle(x1, y1, x2, y2); // <-- As mentioned
surface.Release();
}
Sorry Gilbert I didn't understand your post till now about the triangles and rectangle. I've got it set up where it is one rectangle or as it appears in the game 4. But I still can't get it to decrease so if anyone can help me with that I'd appreciate it. Thanks again Gilbert for all your help.
And if anyone can help me get the meter to decrease look at my script above in my last post. I don't want to repost cause it is so big and I don't want to be a burden by posting too many big post unless needed.
Thank you to anyone that can help me in advance.
You can edit your posts. Just click Modify in the top right corner.
Usually, the background or "empty" color is drawn first, spanning the whole width of the health bar.
Then, a second rectangle is drawn above it, resized to reflect the health. All you need to do is convert the health value into a pixel width, then draw the second rectangle with x1+width instead of x2.
To convert the health value into the pixel width, multiply it by the width of the full bar, then divide it by the current maximum health.
OK Khris do you mean for me to do this?
surface.DrawRectangle(x1,y1,x1+width,y2);
and then after that what do you mean by converting the health value into pixel width and multiplying it by the Width of the full bar and dividing it by the current maximum maximum health. Can you give me a sample script please. Thank you for helping.
Did you follow my advice by setting the "surface.DrawingColor=13;" to "surface.DrawingColor=col;"? This is the most crucial part.
The DrawRectangle() thing is just cosmetic. It shouldn't affect much whether you change it or not.
From my quick check the DrawPercentBar() function seems to be okay, as it already involves drawing a black rectangle of maximum length first and then draw a new coloured bar over it. Please check whether the parameters passed to this function are set correctly when it's called, and not, say, having some of the orders mixed up or passing some of the values wrongly.
You kick ass. It is working with little trouble. Only issue is there is a tad of life left when the battle is over. But it probably won't be noticed in my game. Thank you so much.
Hmmm do you mean that the enermy's lifebar does not appear as zero when he's slain?
Just my guess (the codes are quite long, so I refuse to read all of them ;) ): Probably you end the battle immediately when the HP of this enermy reaches 0, but the lifebar is not updated. You may try putting an additional call to display the enermy's lifebar before ending a battle and see if that makes a difference.
Or change the order of events:
-enemy loses HP
-enemy's life bar is updated
-check for enemy.HP <= 0
OK sorry I didn't respond sooner but I tried looking for what you put Kris but couldn't find the codes you referred to. I think this may be where the problem is. But I'm not sure.
here is the code
function ON_ACTION_ACTIVE (int A, int B) {
// triggered when attacker's (A) action goes into the active phase (frame == active_frame)
// defender's (B) active action can be checked to possibly block the attacker
//
// Note: this function called for each of the fighters, provided one is attacking
// so A may represent a GOBLIN and B - a FIGHTER,
// or B is GOBLIN and A is FIGHTER,
// depending on who is attacking now!
//
// if A attacks (active phase)
if ( IsAction(A, ACTION_ATTACK1) || IsAction(A, ACTION_ATTACK2 ) ) {
// if B is not defending (or maybe performing, but not in active phase)
if ( IsAction(B, ACTION_PARRY) == 0 && IsAction(B, ACTION_DODGE) == 0 ) {
// if attacker has enough weapon_use skill and some luck
if (GetPlayerWeaponUse(A) - Random(Weapon_use_Max) >= 0) {
// ...and has enough stamina
if (GetPlayerStamina(A) > 0) {
// then hit defender
int health_after_hit = GetPlayerHealth(B) - GetPlayerStrength(A);
SetPlayerHealth(B, health_after_hit);
ForceAction(B, ACTION_RETREAT); // forces defender to back off
StopAction(A); // stop active phase (so the attacker won't hit the defender repeatedly!)
}
}
// winning conditions
// (you can put a code to set up some global variable to indicate who wins
// and exit the room here)
while (GetPlayerHealth(B) <= 0) {
Display("Player %d wins!", A + 1);
QuitGame(1);
}
}
}
}
The participants' health is stored in Player[].health.
Look at the function DrawPercentBar(), that's the one that draws the rectangle showing the health.
The function that calls it is right below.
Sorry I took so long I've been trying to figure it out on my own but nothing seems to do it here is the script you told me to look at.
function DrawPercentBar(int x, int y, int width, int length, int col, int percent) {
percent = AdjustValue(percent, 0, 100);
int colored_length = (length * percent) / 100;
RawDrawBar(x, y, x+length, y+width, COLOR_BLACK);
if (percent > 0) RawDrawBar(x, y, x+colored_length, y+width, col);
}
Actually there shouldn't be any problem with the bar drawing function itself. Instead the problem arised from when you declare one of the character has won.
I quickly looked up a few posts earlier I think it may be this part:
...
// winning conditions
// (you can put a code to set up some global variable to indicate who wins
// and exit the room here)
while (GetPlayerHealth(B) <= 0) {
Display("Player %d wins!", A + 1);
QuitGame(1);
}
...
You may add a DrawStatusBars() here to force redrawing of the bars:
...
// winning conditions
// (you can put a code to set up some global variable to indicate who wins
// and exit the room here)
if (GetPlayerHealth(B) <= 0) {
DrawStatusBars();
Display("Player %d wins!", A + 1);
QuitGame(1);
}
...
(Note that I also changed the 'while' to 'if' as it's not logically correct to check it continuously using 'while', but as you cann QuitGame() there it wouldn't make visible difference at the moment.)
Thank you but I tried that and now I get this
Failed to save room room3.crm; details below
room3.asc(394): Error (line 394): Undefined token 'DrawStatusBars'
That function was in the long listing of codes you posted in one of the posts. Does this exist in your current code?
Yes it is in my current code.
I was thinking I don't know if you'd want to but I thought I could give you a link to the thread that I got this from. It is on this site it's just a real old post. If you don't it's OK I know your busy with a lot more than just me I just thought maybe if you and I both fiddled around with it one of us might find the problem faster.
Just to make sure, was that function declared in the same room script as the "winning" part, or, was it in the global script?
If it was in the global script, put on top of the room script the following line:
import function DrawStatusBars();
I believe it is in the room script but I could be wrong. Cause I looked through Global script of which is way smaller and couldn't find it this is my global
// Automatically converted interaction variables
int IntVar_Global_1 = 0;
export IntVar_Global_1;
// main global script file
#sectionstart game_start // DO NOT EDIT OR REMOVE THIS LINE
function game_start() {
// called when the game starts, before the first room is loaded
Debug(4,1);
}
#sectionend game_start // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart repeatedly_execute // DO NOT EDIT OR REMOVE THIS LINE
function repeatedly_execute() {
// put anything you want to happen every game cycle here
}
#sectionend repeatedly_execute // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart on_key_press // DO NOT EDIT OR REMOVE THIS LINE
function on_key_press(int keycode) {
// called when a key is pressed. keycode holds the key's ASCII code
if (IsGamePaused() == 1) keycode=0; // game paused, so don't react to keypresses
if (keycode==17) QuitGame(1); // Ctrl-Q
if (keycode==363) SaveGameDialog(); // F5
if (keycode==365) RestoreGameDialog(); // F7
if (keycode==367) RestartGame(); // F9
if (keycode==434) SaveScreenShot("scrnshot.bmp"); // F12
if (keycode==19) Debug(0,0); // Ctrl-S, give all inventory
if (keycode==22) Debug(1,0); // Ctrl-V, version
if (keycode==1) Debug(2,0); // Ctrl-A, show walkable areas
if (keycode==24) Debug(3,0); // Ctrl-X, teleport to room
}
#sectionend on_key_press // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart on_mouse_click // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(MouseButton button) {
// called when a mouse button is clicked. button is either LEFT or RIGHT
if (IsGamePaused() == 1) {
// Game is paused, so do nothing (ie. don't allow mouse click)
}
else if (button== eMouseLeft) {
ProcessClick( mouse.x, mouse.y, mouse.Mode );
if (mouse.Mode == eModeLookat)
{
Display("Default Controls for Player 1:[Up arrow - Attack 1[Left arrow - Attack 2[Down arrow - Parry/Block[Right arrow - Dodge");
}
}
else { // right-click, so cycle cursor
mouse.SelectNextMode();
}
}
#sectionend on_mouse_click // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart interface_click // DO NOT EDIT OR REMOVE THIS LINE
function interface_click(int interface, int button) {
if (interface == ICONBAR) {
if (button == 5) { // use selected inventory
if (player.ActiveInventory != null)
mouse.Mode = eModeUseinv;
}
else if (button == 6) // save game
SaveGameDialog();
else if (button == 7) // load game
RestoreGameDialog();
else if (button == 8) // quit
QuitGame(1);
else if (button == 9) // about
Display("Adventure Game Studio v2 run-time engine[[Copyright (c) 1999-2003 Chris Jones");
} // end if interface ICONBAR
}
#sectionend interface_click // DO NOT EDIT OR REMOVE THIS LINE
function cEgo_Look()
{
DisplayMessage(999);
}
function cEgo_Interact()
{
DisplayMessage(998);
}
function cEgo_Talk()
{
DisplayMessage(997);
}
function dialog_request(int param) {
}
If they are in the same script, check one more thing. If the function ON_ACTION_ACTIVE() is before DrawStatusBars(), move ON_ACTION_ACTIVE() down so it's below DrawStatusBars().
Sorry that didn't work either. It loaded up but it also did the same thing it always does.
By the way if I ever figure out whats wrong with it do you think Scopiorus would mind me posting a template as long as I give him credit. I mean so other people can use it too.
One last resort. Try adding the following line after the call to DisplayStatusBars() in the winning part and see if it helps.
Wait(1);
Well I tried it and it didn't work.
How much work do you think it would take to revert the meters in to HP numbers and do you think it would go down to zero if I did put numbers instead.
It's very easy.
For example, you can just hack your original function to add text on it:
function DrawPercentBar(int x, int y, int width, int length, int col, int percent) {
percent = AdjustValue(percent, 0, 100);
int colored_length = (length * percent) / 100;
RawDrawBar(x, y, x+length, y+width, COLOR_BLACK);
if (percent > 0) RawDrawBar(x, y, x+colored_length, y+width, col);
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = 15; // <-- Change it to a better colour if not very readible
surface.DrawString(x, y, Game.NormalFont, "%d", percent);
surface.Release();
}
Well I've figured out that it stops at 4 HP if that helps any. Thanks for telling me how to get the HP numbers. Now I guess I can look over my script for the number 4 maybe I'll find the problem that way.