[SOLVED] Using a GUI button to change Room's Object graphic and run a script?

Started by Nerren, Sun 08/12/2024 16:30:55

Previous topic - Next topic

Nerren

I'm having a hard time with a fairly simple script I'm trying to implement, and would greatly appreciate any assistance in getting this thing ironed out.

I am developing an RPG, and have a battle room set up.  I have a function call that passes the monster name to the room, so when the player enters battle, it does: EnterBattle(##) where ## is the monster number.  Upon entering the room, it grabs the health, armor, etc from the monster list I have.  The battle screen is similar to the old Quest for Glory games where the player is on one side and monster is on the other.  I have a GUI that I named gBattleGUI that pops up in that room.  On that GUI are buttons for different attack types and spells the player can use depending on their class and spells currently known. 

I am not using the character for this, instead I have a different set of animations for this battle room that I have set to objects.  So I have a oHero object and an oMonster object.  The oHero, upon room load, changes to a different sprite depending on weapon equipped, etc, so it matches the player's class, equipped weapon, etc.

I want the btnMelee button in gBattleGUI to change the oHero.Graphic to 123, then run a mobHP = mobHP - 5 script to reduce the monster's HP by 5 (this will be replaced with an actual script later based on monster armor, player weapon use, type of weapon, etc.  But for now I'm having a hard time passing whatever variables I need for this to even work.

In the gBattleGUI I have an on-click event for the btnMelee button:
Code: ags
function btnMelee_Click() {
  
MeleeAttack();

  }


At the very top of GlobalScript.ash, I have the import:
Code: ags
import function MeleeAttack();


Then in my room299.asc (the battle Room) I have a function set up:

Code: ags
function MeleeAttack() {
  
if (equippedWeapon.ID == 1){  // If character is wielding a sword,  change image to depict sword attack.  
    Wait(20);
    oHero.Graphic = 228;  // Swing Sword
    
  }
  
  else if (equippedWeapon.ID == 2){ // If character is wielding a dagger,  change image to depict stabbing with a dagger.
    oHero.Graphic = 219;

  }
  
  else {
    oHero.Graphic = 230;
   }  
}


I will be tweaking everything, but for now I'm just trying to get it to run.  If I do the changes manually in the room code, it works fine.  But when I try to invoke the image changes from the GUI button, the game compiles and runs, but as it tries to launch, I get a crash and an error popup window:

Loading game failed with error:
Script link failed.
Error (line unknown): in GlobalScript.ash: 1 unresolved imports (last: MeleeAttack).
The game files may be incomplete, corrupt or from an unsupported version of AGS.

I did try recompiling, to no avail.  The issue persists.

Is there a better way to call a function, or a more practical way for me to change room object graphics and run calculations against both local and global variables from a GUI button?

Thanks in advance!

Bill



Crimson Wizard

In AGS you cannot import functions from the room scripts, because they would depend on which room is loaded.
You will need to change how your code is organized.

I think the best way may be to script the combat system in a separate script module, use Characters instead of objects, and only setup and activate combat from the room script in which it takes place, by setting variables and calling functions imported from that module.

EDIT:
If you must use room objects, or anything from the room, in your combat module for any reason, then one approach would be to declare pointer variables (or attributes) in that module, which are then assigned in room script.

To give a simple pseudo example:
Code: ags
// in Combat.ash
import Object* HeroObject;
import Object* EnemyObject;

// in Combat.asc
Object* HeroObject;
Object* EnemyObject;
export HeroObject, EnemyObject;

// in roomX.asc
function Room_Load()
{
    // assign these Combat module pointers to local room objects
    HeroObject = oHero;
    EnemyObject = oEnemy;
}

Although I normally recommend using Characters for this kind of thing.

Nerren

Got it, I will just revamp and use characters instead.  No use reinventing the wheel on this kind of thing.

Thanks again for the advice and info.

Bill

Khris

Just for reference, calling room functions from the global environment is possible using CallRoomScript().

In the click handlers for the buttons:
Code: ags
  CallRoomScript(1); // 1 = melee attack
Code: ags
  CallRoomScript(2); // 2 = block

In the battle room script, below the other functions:
Code: ags
function on_call(int p) {
  if (p == 1) MeleeAttack();
  if (p == 2) Block();
}

The parameter is simply an int value of your choosing so you can run different room commands/functions.
To keep things more readable you can use an enum for the various int values.

SMF spam blocked by CleanTalk