Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - duckwizard

#1
Seems to be a color depth thing.  I copied each one to the clipboard ("open in default editor" doesn't work for me, Photoshop says the file could not be found), pasted into photoshop, changed mode to RGB, copied, replace from clipboard, and now they look fine.

Weird that none of my other sprites (all imported from GIFs) got messed up in the import.
#2
Hey,

Last week I downloaded 3.1.2 since 3.2 wasn't linked from the website (hadn't dove into the forums yet).

I got pretty far into making a game with 3.1.2 before I found out that 3.2 is available and has some nifty new features (like characters view in room editor) and is all around better.  So I grabbed 3.2 and upgraded my game.

Thankfully I made a backup because now some my GUIs are messed up.  They were just the standard GUIs from the Sierra template game.  The dropdown bar is now just completely black, and the inventory screen just has black boxes instead of buttons.

When I open the GUIs in the GUI editor they look fine.  Save/Load GUI looks fine.  My custom GUIs seem to look fine.

The game is 32-bit color, if that makes a difference.  I am planning to redo the GUIs at some point anyway, but not until near the end of development.  And it's making it hard to test that I can't see my GUIs!  Any advice?
#3
Thanks for the reply.  I've been using AGS for under a week now so I wasn't sure if I was doing something bad.

The reason I added those unused parameters was just to make the calls compatible with the standard Animate method.  At the time I was replacing many lines of Animate() with AnimateDS() and it seemed like the path of least resistance.  *shrug*  Plus now I can just add or remove the "DS" to switch back and forth if I need to for some reason.


I'll look at the frame speed.  Does Animate() use the sum of frame speed and delay as you show here?

#4
TL,DR: Need multi-frame animated turns that work even when navigating pathfinding waypoints.  Currently using a lot of PauseGame() to get the effect.  Need to know if that's OK and if there's a better way to do it.

I have a situation where it's important for my character to have multi-frame animated turns (i.e. a single diagonal frame is not sufficient).

I scanned the forums and most suggestions amounted to intercepting the walk click, firing a dummy "bullet" character from the ego's position to the click, and then use that dummy character's loop number to figure out which direction to animate to, then processing the click for the character.

After thinking about this I realized it wasn't sufficient because if the character has to navigate around a complex path, he will turn several times during that.  So with the "bullet" idea you get the initial turn (from stopped to the direction of initial walk) but you don't get animated turns while walking.

So I came up with a new idea where I have some logic in repeatedly_execute() that checks A) if the character is moving, and B) if his loop is different from his last loop.  If both these conditions are met, it should simply do the appropriate turning animation(s) to get from the old direction to the new direction.

The problem I had with this was that executing the animations using Animate() caused the actual movement to be cancelled.  So you would click and he would turn, but then he wouldn't actually walk unless you clicked again (or he was already facing that direction).  Checked the manual, and yep - Animate() stops the character if he is moving.

So I tried writing a function to do the animation manually, incrementing/decrementing the frame as appropriate and then calling Wait() in between.  Turns out Wait() doesn't pause his walking so it just ends up being really strange and not working at all.  So I added PauseGame() and UnPauseGame() calls around that to pause his walk.

Code: ags

//Animate Don't Stop
//always blocks, ignores blocking style
//always plays once, ignores repeat style
function AnimateDS(this Character*, int loop, int delay, RepeatStyle rep,  BlockingStyle block, Direction dir)
{
  this.Loop = loop;
  int numFrames = Game.GetFrameCountForLoop(this.View, this.Loop);
  
  
  if(dir == eBackwards)
  {
    this.Frame = numFrames - 1;
    while(this.Frame > 0)
    {
      PauseGame();
      Wait(delay);
      UnPauseGame();
      this.Frame--;
    }
  }
  else
  {
    this.Frame = 0;
    while(this.Frame < numFrames - 1)
    {
      PauseGame();
      Wait(delay);
      UnPauseGame();
      this.Frame++;
    }
  }
  
  PauseGame();
  Wait(delay);
  UnPauseGame();
}


The good news is, it works perfectly.  Animated turns work even while navigating a complex path.

The bad news is, I feel really unsure about subverting PauseGame() to this effect.

This effect is only necessary for a small part of the game (when the character is on a horse) and I don't *think* there will be much background stuff happening (which would get artificially choppy when the turning was happening) but even so it feels wrong to me.

So my question is - what reasons are there why doing this could be bad?  And is there a simpler way to effect animated turns, even while navigating, without resorting to this?
#5
Advanced Technical Forum / Re: Callbacks
Fri 11/03/2011 00:52:07
Quote from: Khris on Fri 11/03/2011 00:23:11
Just for reference, I'd define an enum with all the room events triggered by global stuff, then use CallRoomScript / on_call().

You're right, that's a decent way of doing it as far as readability is concerned.  I still like callbacks better personally, and the plugin took 5 minutes to make, so why not?  And I figured some people might want to do it who don't have a C++ compiler, so... *shrug* To each his own, I guess (and my "own" is to avoid on_call wherever possible because I hate it for some reason I can't explain)

Quote from: Khris on Fri 11/03/2011 00:23:11
Plus, you can always split the logic into several functions; nowhere does it say you have to handle all of it in a single if-else if mess. In fact that's what I'd do anyway if I had tons of possible events like that; the thing is you rarely are in that situation and even then, the logic in this case is already split among rooms.

Sure, but even if you split the logic up, you still need the if-else to call the functions that you moved the logic into.  I would even argue that the enums and the callbacks are functionally equivalent - both use a variable to decide what function to call.  The callbacks simply remove the need for the switch block by storing the actual function rather than a numeric abstraction if it.

Plus, the plug-in has the bonus of crashing if you use it wrong :)
#6
Zikes!

Where did you get those new backgrounds?  Were they in the QFG1VGA resources, sitting unused?  Or did you make them yourself?  Either way, I for one am looking forward to playing.
#7
Advanced Technical Forum / Callbacks
Thu 10/03/2011 23:43:18
I wasn't able to use QueueScriptFunction for what I originally wanted, but it did come in handy for something else - namely callbacks.

This is a really simple plugin (surprised it hasn't been done already, judging by my scan of the plugins board).  It exports two functions

void ExecuteFunction(String fnName, int global)
void ExecuteFunctionParam(String fnName, int global, int param)

The first form just executes the function called fnName.  If global is zero, it executes that function in the current room script.  Otherwise, it executes that function in the global script.

The second form does the same, but allows you to pass a single int parameter to the function you want to call.

Here is the DLL if anyone is interested.

Example use case for callbacks:

My character has a wallet with a certain amount of money in it.  When he uses the wallet on something, I want a GUI to come up that asks him how much money he wants to give.  The GUI has a "give" button that closes the wallet GUI.  And then what happens?

Without callbacks, you probably stored some variable that said whom or what you were giving the money to. Then, in the WalletGiveButton_OnClick handler you do ALL the logic for every possible thing you could give money to.

With callbacks, your OpenWallet function takes the name of the function that you want to be called when money is given:

Code: ags

//room5.asc
function oBeggar_UseInv()
{
	if(cEgo.ActiveInventory == iWallet) // not an apple product (yet)
	{
		OpenWallet("gaveBeggarMoney");	
	}
}

function gaveBeggarMoney(int howMuch)
{
	if(howMuch < 20)
	{
		Display("What a cheapo!");	
	}
	else
	{
		BeggarGivesTreasureMapOrSomething();	
	}	
}

//GlobalScript.asc
String walletCallback;
function OpenWallet(String roomCallback)
{
	walletCallback = roomCallback;
	gWallet.Visible = true;
}

function btnWalletGive_OnClick()
{
	if(walletCallback == null) return;
	ExecuteFunctionParam(walletCallback, 0, sldWalletAmount.Value);
	walletCallback = null;
	gWallet.Visible = false;
}



Now whenever you want to open the wallet from any room script, you can just pass in a string with the name of the room function that you want to be called when the player has selected the money amount.  The money amount will be passed in to that function.  Whee!

Tiny source code (didn't bother to rename the template source file)

Hereby public domain (on my end anyway - source contains a copyright message from CJ), feel free to use, improve, or lambaste me for making something useless :)

For example, you could add a way to call a function with two parameters as that's supported by QueueScriptFunction.  But I don't have a need for it right now, so I didn't.

Edited: forgot to clean up wallet GUI in use case code; it probably would have crashed.  Be careful :)
#8
Khris, that works perfectly.  Didn't know you could intercept mouse events at the room level.  Very cool.

Even cooler that it waits until my blocking call finishes and then bubbles the event up to the global processor!  I wouldn't have expected that (separate event loops for animation and input).
#9
Thanks for the reply!

Quote from: Matti on Thu 10/03/2011 20:01:28
Couldn't you just play a blocking stand-up animation in case the player clicks somewhere while the character is still sitting? If it's blocking the character won't start walking. You could then set variables for the coordinates the character is supposed to walk after standing up.

Sure, but how would I intercept the click if the player is in walk mode?  There is no "any kind of click anywhere in the room" event.  Even if I make a hotspot that covers the whole floor (or the whole room), and assign "other click on hotspot" event, walking is the one kind of click that won't fire that event.

Am I missing something?
#10
I have a spot that when you interact with it, it causes cEgo to walk there and play an animation to sit down.  That works great.

But now I want it so if you walk somewhere else, he will play a "stand up" animation before he starts to walk.

I tried making a 1 pixel region where he is programmed to sit, and when cEgo leaves that region it plays the stand up animation.  But by that time he is already walking, so it's too late for this to work.

I could work around this by disabling walk and forcing you to interact with something (like the rest of the floor I guess) in order to stand up, then re-enabling walk.  But that is not ideal.  So I thought I would check if anyone has ideas for making this happen.

There is probably something I could do with invisible dummy characters or dummy objects.  I will try to mess with that.  But I'm hoping there's an elegant solution because I am a little OCD when it comes to inelegance and I go to great (even ridiculous) lengths to avoid it.
#11
I did know about member functions, but that didn't occur to me.  It's very clever.  Thanks!
#12
I am using v3.1.2 SP1 (Build 3.1.2.82).  Just downloaded it a few days ago.  Windows 7, 64-bit, if that matters (which I don't think it does, since it seems like an error that was designed to be thrown in this situation.  Unfortunately.)
#13
Quote from: Wyz on Thu 10/03/2011 00:12:36
I've (mis)used the QueueGameScriptFunction function to create an event system for some of my plug-ins and even when the function was not defined it never made my game crash. Could you give an example about how you call the function?

It doesn't seem like there are many other ways to call the function:

Code: ags

engine->QueueGameScriptFunction(funcName, 0, 0);


where funcName contains the name of the function I wanted to call in the room script.  If the function exists, it gets called.  If not, I get a crash: "Error: prepare_script: error -18 (no such function in script) trying to run cMerlin_Talk (Room 9)"
#14
I guess it is a lot of trouble.  But if I have a sidekick character in my game for example, who is there with me in all 244 rooms, and he has to say interesting things about each room, then yeah - his Talk() function in the global script is going to be pretty gnarly.  And I just think that stuff specific to a room belongs in the room script - it's just what makes sense to me as a programmer.

Ideally I would check for the room's cChrisJones_Talk function, and if it doesn't exist I would check for the cChrisJones_Talk function in the global script.  Thus it really wouldn't be that much trouble to get what I think is more organized and readable game code (the unique code in my plugin comprises about 30 lines).

But, if there's really no way to "look before you leap" when it comes to GameScriptFunction, then I guess I'll have to give up.
#15
BTW, I finished implementing my plan with a global struct variable.  Ugly, but it worked great.  Still, the plugin method would be far cleaner.  In fact, maybe someone has already made a plugin like this - I tried to find evidence of that but couldn't.
#16
monkey_05_06:

See my new thread at http://www.adventuregamestudio.co.uk/yabb/index.php?topic=43057.0 - basically I was trying work out a system similar to this before I realized a plugin could do an even cleaner job.  So I've given up on struct passing.  But FWIW, here's what I was trying to do.

I had an unhandled_event function that would figure out which type of thing was being clicked and which type of action.  Then it would grab the ID of that thing.  Then it would bitwise-pack those three pieces of data into an int so it could be passed to on_call using CallRoomScript. 

Then I wanted a function that could be called from on_call in the room script which would unpack the data into a struct, setting up character/object/invitem references and return the struct for use in on_call.  So your on_call would look like this:

Code: ags

//room1.asc
function on_call(param)
{
	UnhandledEvent e = UnpackUE(param);	//this would unpack the param into an UnhandledEvent struct if it had gone to plan
	
	if(e.targetCharacter == cChrisJones && e.action == eaTalk)
	{
		cChrisJones.Say("You're in room 1!");
	}
	else if(e.targetObject == oAwesomeThing && e.action == eaInteract)
	{
		cChrisJones.Say("Hey! Don't take my Awesome Thing!");
	}
	//etc
}


Anyway, I realized the plugin API is simple enough and if I can solve the problem in my other thread then I'll be golden.  Thanks for the quick reply, though!
#17
Not sure if this belongs in the Module forums instead, but it is pretty Technical :)

I was kind of bummed on the way character events are only handled in the global script - it seemed like it would be far more useful if they could be handled in the room script instead (so characters can do different things in different rooms without having a giant mess of if/else in their single event handler).

So I wrote a simple plugin that lets you dispatch an unhandled event to the room script from unhandled_event().  When there is an unhandled event, it will figure out the character (or object) name and the action that wasn't handled, and then it will try to call the corresponding function in the room script.

Example: You have a character called cChrisJones.  When you're in room 1 and you look at him, he should say "You're in room 1!" and when you're in room 2 he should say "Toto, I've a feeling we're not in room 1 anymore!":

Code: ags

//room1.asc
function cChrisJones_Look()
{
        cChrisJones.Say("You're in room 1!");
}

//room2.asc
function cChrisJones_Look()
{
        cChrisJones.Say("Toto, I've a feeling we're not in room 1 anymore!");
}


I compiled my plugin and it works great out-of-the-box.  Except for one thing.  If I had a room with cChrisJones in it, and I didn't supply a cChrisJones_Look() function in that room script, it crashes because I'm trying to call a function that doesn't exist.

So my question is: is there any way to check if the function exists before I call it with QueueGameScriptFunction?

Thanks!

Edited: forgot to close my code block
#18
Edit - found this thread http://www.adventuregamestudio.co.uk/yabb/index.php?topic=13458.msg162111#msg162111 after a lot of googling.

Answer: Nope, can't do it.  Have to use a global variable (ugh)
#19
Is there any way to return a struct from a function?

MyStruct foo() { ... } gives me "Cannot return entire struct from function."
MyStruct* foo() { ... } works if I make MyStruct a managed type, but then I can't create a MyStruct.

What should I do?
#20
No, I did not know about those functions.  LockViewAlign makes my life a lot easier - thanks for the tip!

I still think anchor point control would be neat, but I won't begrudge anyone for not getting around to it.
SMF spam blocked by CleanTalk