A couple of questions actually.
Firstly, using (character[EGO].view==20) doesn't appear to work in a statement like this:
if ((moleret == CD_COLLISION) && (character[EGO].view==20) && (GetGlobalInt(6)==0)) {
blah blah blah...
}
I'm not sure why or what I can do instead.
Secondly, I have a collision detection set up to, once detected (and if GlobalInt 6 == 0), run a function which like this:
function InjureMe() {
Ã, if (GetGlobalInt(6)==0) {
Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã,Â
Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, SetGlobalInt(6, 1);
Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, ...blah blah...
Ã, SetTimer(2, 80);
Ã, }
Ã, }
...and in the repeatedly_execute section:
if (IsTimerExpired(2)==1) {
Ã, Ã, SetGlobalInt (6, 0);
Ã, Ã, Wait(1);
Ã, Ã, }
I have it set up this way so that, if the character's collide and if the player isn't currently "being injured", he will get injured, and for 2 seconds afterwards, will be "invinsible" and unable to get harmed again. I have to use a Timer function instead of Wait so it isn't blocking.
The problem is that after being injured once, if the character just stands still, the interaction won't happen again at all. I have to have the character moving (or something updating the script) for it to allow him to get injured again. That's why I put the Wait(1); in, but it doesn't seem to do anything.
I'm pretty stumped on this... can anyone help?
There's so many nitpicky things on AGS that could scre you up, but here's what I've noticed:
function InjureMe() {
Ã, if (GetGlobalInt(6)==0) {
Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, Ã, ...blah blah...
Ã, SetGlobalInt(6, 1);Ã, // I'm sure you have this, right? :)
Ã, SetTimer(2, 80);
Ã, }
Ã, }
And also:
if (IsTimerExpired(2) == 1 && GetGlobalInt(6) > 0) {
Ã, Ã, SetGlobalInt (6, 0);
Ã, Ã, //Wait(1);
Ã, Ã, }
Maybe that would help some. There may be some thing in your code (like under ...blah blah...) that could mess everything up.
Pumaman: You can't bold stuff under the [ code ] [ / code ] tags, which might be useful like in this case! You sense danger!
I did indeed have the SetGlobalInt line there, I should've mentioned it. I'll modify my original post.
I followed your suggestion with the rest anyway, but it made no difference. I'm not sure but I don't think the "(GetGlobalInt(6)>0) " line is necessary. As I understand it, IsTimerExpired only returns 1 once so the way it's setup to run directly after the function has executed, it shouldn't be a problem. I think, anyway.
Oh ok. I downloaded the AGS help file, so I could read on the functions because I don't remember those kinds of details.
Well, here's my deductions. Your triggering condition (the if statement that checks to call InjureMe()) may have some sort of glitch.
if the condition is (moleret == CD_COLLISION) && (character[EGO].view==20) && (GetGlobalInt(6)==0)
I'm not exactly sure what molert and CD_CONDITION, or mayb even the view may affect it. but I would make sure that you have the logic right in that condition and that all the flags are reset when the character stops "blinking" (well, I'm thinking about a console game where you get hit and you blink for a bit)
moleret/CD_COLLISION are due to the Character Collision plugin I'm using.
I'll recheck everything tomorrow when I'm not falling asleep. Thanks for your help so far, anyway.
Yeah, where are you calling InjureMe() from? It's probable that your logic there isn't running while the player is standing still.
Also, in terms of the view it's important to note that the character[].view variable is the view number minus 1. So to check for view 20, do:
if (character[EGO].view == 19)
This is a pain I know, and were I to start AGS from scratch now I'd make sure it didn't do this, but unfortunately we've got to live with it.
Hmm, I hate having problems like this where I just can't see what's wrong logically.
Here's basically all of the scripting involved.
int moleret = spriteSpriteColDetect (EGO, CD_CHARACTER, egoslot, MOLERAT, CD_CHARACTER, 201);
///////////////////////////////
if ((moleret == CD_COLLISION) && (character[EGO].view==19) && (GetGlobalInt(6)==0)) {
if ((Random(luck))<2) {
TypeLineKaya (510, 130, 50, 1, 12, 200, 0, -1); //miss
}
else {
mondmg = ((str + wpnstr) + (RandomEx(((str/5)-str%5)*4,str)) - (RandomEx(((mondef/5)-mondef%5)*4,mondef)));
if (mondmg<1) mondmg=1;
kayahp -= mondmg;
DisplayDMG ();
Display ("Molerat takes %d damage! Molerat's HP is %d", mondmg, kayahp);
}
}
else if ((moleret == CD_COLLISION) && (character[EGO].view!=19) && (GetGlobalInt(6)==0)) {
InjureMe();
}
Basically, this is defining a collision between the two characters (which works fine). If that collision happens and the character is in the "attacking" view, run the script regarding damage to the Molerat. If it's any other view, run InjureMe...
function InjureMe() {
if (GetGlobalInt(6)==0) {
SetGlobalInt (6, 1);
SetCharacterView (EGO, 22);
//displaydmg
AnimateCharacterEx (EGO, character[EGO].loop, 0, 0, 0, 1);
SetCharacterView (EGO, 19);
SetTimer(2, 80);
}
}
Then in repeatedly_execute:
if ((IsTimerExpired(2)==1) && (GetGlobalInt(6)>0)) {
SetGlobalInt (6, 0);
//Wait(1);
}
I don't know... when I look at it, I can't see what's wrong. The only thing that strikes me is that it -seems- like something isn't being updated until my character has moved. Though, that doesn't seem to make sense because I can move my character after it's been injured, and then stop it, and it still won't run InjureMe again when the collision occurs once more. The character has to be moving at the time of the collision for it to run the code again.
The first block of code that you posted -- is that in repeatedly_execute?
No, that's just at the end of my global script.
Then what function it's in?
Erm, it's not in a function. It's just at the end of the global script.
It must be in some function, else you cant tell the engine where to execute it.
Hmm, I thought you could just tack things on the end. In that case, I'm not sure where to put it exactly. I mean, almost everything I've added to the global script has gone outside of the pre-existing functions and they all work fine. I've been trying to avoid putting too many thing in repeatedly_execute in case it slows the game down.
Quote from: Kinoko on Mon 16/08/2004 14:40:03
I mean, almost everything I've added to the global script has gone outside of the pre-existing functions and they all work fine.
Actually I think that's quite strange, I wonder why they'll work and even compiled without errors.
Stuffs put outside of any functions are for initialisations and variable declarations, etc. only.
If you want some actions to be done in game, the scripts must be put into some functions, for example if you choose an interaction response to run script, it will create some function like room_a(), etc in the script, so everything should be in functions.
Judging from your code, I think you want it to happen every game loop right? Then it
should be in repeatedly_execute(). You're right in saying that if you execute many stuffs all at once the engine may be slowed down with slower computers but you cant prevent it if you really want them to run together.
Whoa, sorry sorry... my mistake. That code is actually in on_key_press... I don't know what I was thinking.
I've shuffled it all around now, and put the code necessary into repeatedly_execute, and InjureMe now works fine.
The problem now is just that the attacking part of the code won't work.
This is all in repeatedly_execute:
if (character[EGO].loop == 0) {
Ã, egoslot = 202;
Ã, }
else if (character[EGO].loop == 1) {
Ã, Ã, egoslot = 203;
Ã, }
else if (character[EGO].loop == 2) {
Ã, Ã, egoslot = 204;
Ã, }
else if (character[EGO].loop == 3) {
Ã, Ã, egoslot = 200;
Ã, }
///////////////////////////////// MONSTERS ///////////////////////////////
moleret = spriteSpriteColDetect (EGO, CD_CHARACTER, egoslot, MOLERAT, CD_CHARACTER, 201);
moleret2 = spriteSpriteColDetect (EGO, CD_CHARACTER, 68, MOLERAT, CD_CHARACTER, 201);
//////////////////////////////////////////////////////////////////////////
Ã,Â
if (character[EGO].room == 1) {
Ã, if ((moleret == CD_COLLISION) && (character[EGO].view==19)) {
Ã, Ã, Ã, if ((Random(luck))<2) {
Ã, TypeLineKaya (510, 130, 50, 1, 12, 200, 0, -1); //miss
}
else {
mondmg = ((str + wpnstr) + (RandomEx(((str/5)-str%5)*4,str)) - (RandomEx(((mondef/5)-mondef%5)*4,mondef)));
if (mondmg<1) mondmg=1;
molehp -= mondmg;
DisplayDMG ();
Display ("Molerat takes %d damage! Molerat's HP is %d", mondmg, molehp);
}
Ã, Ã, Ã, }
Ã, if ((moleret2 == CD_COLLISION) && (character[EGO].view!=19) && (GetGlobalInt(6)==0)) {
Ã, Ã, Ã, InjureMe();
Ã, Ã, Ã, }
}
It's now just the line if ((moleret == CD_COLLISION) && (character[EGO].view==19)) that doesn't appear to be working. The collision is fine because it works when I use (IsKeyPressed(88)) instead of the character[EGO].view line. The necessary view is 20, so I have taken 1 off it.
Hmmm try putting a display line in it to check if the view was indeed 20-1, like:
Ã, if ((moleret == CD_COLLISION)) {
/* && (character[EGO].view==19)) {*/
Display("%d",character[EGO].view);
Ã, Ã, Ã, if ((Random(luck))<2) {
Ã, TypeLineKaya (510, 130, 50, 1, 12, 200, 0, -1); //miss
}
else {
mondmg = ((str + wpnstr) + (RandomEx(((str/5)-str%5)*4,str)) -
blah bla....
Also, check if your character is indeed called EGO, not something else.
I don't know why I didn't think of that myself. As far as I can tell, it does indeed seem to be on view 18 instead of 19 (or in actual terms, view 19 and 20) when the collision is detected. 18 (actually 19) is the normal walking view, and when the attack button is pushed, this code runs:
if (IsKeyPressed(88)) {
Ã, Ã, SetCharacterView(EGO, 20);
Ã, Ã, AnimateCharacterEx (EGO, character[EGO].loop, 2, 0, 0, 1);
Ã, Ã, SetCharacterView (EGO, 19);
Ã, Ã, }
So, it seems like maybe the game is checking the collision before this code has had time to change the view to 20. I don't know, I thought my code was fine. When both the collision is happening, AND the view is 20, then blah blah... Especially given that it's in repeatedly_execute. It seems like the first bunch of code shouldn't run until the view is 20.
EDIT: Unless it's just a feature of the character collision plugin that character collisions only count as collisions when they first occur, not AS they're occuring... but the InjureMe code works over and over as long as the collision has happened and continues to happen. That one doesn't seem to need the collision to re-happen.
Sorry for the double post but... *bump*
Anyone have any thoughts on this?
That AnimateCharacterEx call is blocking, so repeatedly_execute won't run while it is in progress. Then, the animation ends and the view gets set back to 19, then finally repeteatedly_execute runs.
This is likely to be the problem.
Ahh, I hadn't remembered that about repeatedly_execute. I moved the code in question into repeatedly_execute_always which still gives an error because of a blocking function, but that's referring to all the Display functions in there which were only temporary anyway.
What I need to put in their place is a non-blocking display function similar to DisplaySpeechBackground that allows the use of %d and %s (and a couple of other properties such as displaysing at specific coordinates and a transparent text window... which I think is being fixed in a later AGS version...?).
The semi-temporary code I have now is:
In repeatedly_execute_always
if (character[EGO].room == 1) {
if ((moleret == CD_COLLISION) && (character[EGO].view==19) && (GetGlobalInt(7)==0)) {
if ((Random(luck))<2) {
// TypeLineKaya (510, 130, 50, 1, 12, 200, 0, -1); //miss
DisplaySpeechBackground (EGO, "Miss...");
}
else {
SetTimer(3, 80);
SetGlobalInt(7, 1);
SetCharacterView (MOLERAT, 23);
AnimateCharacterEx (MOLERAT, character[MOLERAT].loop, 0, 0, 0, 0);
mondmg = ((str + wpnstr) + (RandomEx(((str/5)-str%5)*4,str)) - (RandomEx(((mondef/5)-mondef%5)*4,mondef)));
if (mondmg<1) mondmg=1;
molehp -= mondmg;
//DisplayDMG ();
DisplaySpeechBackground (EGO, "Hit!");
//Display ("Molerat takes %d damage! Molerat's HP is %d", mondmg, molehp);
}
}
}
And in repeatedly_execute:
if (IsTimerExpired(3)==1) {
SetCharacterView (MOLERAT, 21);
SetGlobalInt(7, 0);
Wait(1);
}
It works fine, in that once a "Hit" has been made, I don't want another hit to be able to take place until the timer(3) has expired (which is why I've got GlobalInt(7) in there).
The only problem is that when the character attacks and a "hit" is made, at least two "Hit!"s or a "Hit!" and a "Miss..." appear at the same time immediately. Further attacks will be blocked after that until the timer has expired, but there's that little nanosecond where several will be registered at once. I'm not sure why more than one are making it in at the start...
Well, if it's a Miss, the GlobalInt 7 doesn't get set to 1, so there's nothing to stop the code all running again.
Offhand, I can't see how you'd be getting two hits in a row, though.
Also, there's a workaround for using %d/%s with any command, just do:
string buffer;
StrFormat(buffer, "Molerat takes %d damage! Molerat's HP is %d", mondmg, molehp);
DisplaySpeechBackground(EGO, buffer);
Ahh, I've fixed the code in the "miss" section, thanks for that. I'll keep that workaround in mind, too.
I really don't understand what's happening with the double(or more) ups either... I'm having a similar problem (thread currently in the Beginners Help) with trying to stop an action happening more than once with each key press. It seems to work, but if I keep a key held down, the action will continue to run continuously despite being told in the script not to run again until the first action is completed. I was hoping that if anyone, you'd have an idea of what was happening here ^_^;;; I don't understand it, but it just seems as though when the code is called, certain blocks don't happen quick enough before the code is called again. I really don't know...
EDIT: Well, that problem has been fixed and it seems to have fixed the problem of the double-ups too. I'm not sure why, but things are working well now. Crazy. Thanks for all your help, anyway.