Aller au contenu

Photo

Script Woes - Game Freezing


  • Veuillez vous connecter pour répondre
9 réponses à ce sujet

#1
Morbane

Morbane
  • Members
  • 1 883 messages
This is related to another thread I started - but now the reason for posting has changed.

I am writing a heartbeat script for a persistent feat - all it does is apply a couple of effects if the conditions are met.

The conditions:
In Combat
HitPoints < half 
Number of enemies > Hit Dice + a stat bonus

That is about it - So I am using a while loop to cycle through perceived enemies - this is where the problem starts...

If the PC initiates combat by clicking at a distance on the perceived enemy first the game freezes and dies
If the NPC initiates combat first by attacking first everything is fine.

I know - that is weird aye?

Whats more - right now all there is in the while loop is a SendMessageToPC statement - if the while loop is totally empty of code - other than getnextobjectinshape() nothing locks - but there is no code running - not very usefull - I will post the code if anyone wants to take a poke at this strange script behavior - or maybe there is a more obvious solution??

I have built similar HB scripts before - really complex ones - but this one is giving me grief - I know not why...

:blink:

Modifié par Morbane, 20 juillet 2010 - 02:53 .


#2
Morbane

Morbane
  • Members
  • 1 883 messages
void main()
{
SendMessageToPC(GetFirstPC(), "Uncontrolled Cycling");

object oSelf = OBJECT_SELF;
location lSelf = GetLocation(oSelf);

int nEnemyCount;
int nBonus = GetLevelByclass(class_TYPE_LYCANTHROPE, oSelf);

int nDuration = GetHitDice(oSelf) - nBonus;

if(nDuration
nDuration = 1;

int nBonusMod = GetAbilityModifier(ABILITY_CONSTITUTION);

if((GetIsInCombat(oSelf) == FALSE) || (GetCurrentHitPoints(oSelf) > GetMaxHitPoints(oSelf)/2)) return;


object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oTarget))
{
SendMessageToPC(GetFirstPC(FALSE), "Is Valid");
/*
if(oTarget == oSelf)
{
SendMessageToPC(GetFirstPC(FALSE), "Skip oSelf");
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);
}

if(GetIsEnemy(oTarget, oSelf))
{
SendMessageToPC(oSelf, "In Combat/Is Enemy");
nEnemyCount += 1;
//add one to the count and break out of while loop if quota
if (nEnemyCount > nBonus )break ;

}
*/
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);

}//while
SendMessageToPC(GetFirstPC(), "nEnemyCount = " + IntToString(nEnemyCount));

if (nEnemyCount > nBonus )
{
effect eHitPt = EffectBonu****points(nBonus * nBonusMod);
effect eHaste = EffectHaste();
effect eWild = EffectInsane();
effect eLink = EffectLinkEffects(eHaste, eHitPt);
eLink = EffectLinkEffects(eLink, eWild);

ActiveWereWolf(oSelf);

ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oSelf, TurnsToSeconds(nDuration));
}

}//main

Modifié par Morbane, 20 juillet 2010 - 02:55 .


#3
Morbane

Morbane
  • Members
  • 1 883 messages
effect eHitPt = EffectBonu****points(nBonus * nBonusMod);



This thinks Bonus*HitPoints is trying to say the bad word for poop - lol

#4
Morbane

Morbane
  • Members
  • 1 883 messages
I *think* I found a solution...

I added an if statement that tests if the enemy is being targeted or attacked then to DetermineCombatRound() at the top of the while loop. The freeze seems to have been fixed because of that. but one of the tests - GetCanSeePC(oTarget) - creates a mini loop and a debugging message repeats many many times when the oTarget is killed - BUT the game did not freeze - *whew* - that test wasnt critical but I was just trying to cover all the options for DetermineCombatRound() to fire before the while loop winged out again - so I commented out the GetCanSeePC() function - all seems well.

#include "a_include_mor"

#include "a_inc_lycanthrope"

#include "nw_i0_generic"

#include "nw_i0_2q4luskan"

void main()

{

SendMessageToPC(GetFirstPC(), "Uncontrolled Cycling");



object oSelf = OBJECT_SELF;

location lSelf = GetLocation(oSelf);



int nEnemyCount;

int nBonus = GetLevelByclass(class_TYPE_LYCANTHROPE, oSelf);



int nDuration = GetHitDice(oSelf) - nBonus;



if(nDuration < 1)

nDuration = 1;



int nBonusMod = GetAbilityModifier(ABILITY_CONSTITUTION);



//if(GetIsInCombat(oSelf) == FALSE || GetCurrentHitPoints(oSelf) > GetMaxHitPoints(oSelf)/2) return;



object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);



while(GetIsObjectValid(oTarget))

{

if(GetLastAttacker(oTarget) == oSelf || GetAttackTarget(oTarget) == oSelf

|| GetAttemptedAttackTarget() == oTarget || GetAttemptedSpellTarget() == oTarget)// || GetCanSeePC(oTarget))

{

DetermineCombatRound();

}



SendMessageToPC(GetFirstPC(FALSE), "Is Valid");



if(GetIsEnemy(oTarget, oSelf))

{

SendMessageToPC(GetFirstPC(FALSE), "Is Enemy");



SendMessageToPC(oSelf, "In Combat/Is Enemy");

nEnemyCount += 1;



}



oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);



}//while



SendMessageToPC(GetFirstPC(), "nEnemyCount = " + IntToString(nEnemyCount));



if (nEnemyCount > nBonus )

{

effect eHitPt = EffectBonu****points(nBonus * nBonusMod);

effect eHaste = EffectHaste();

effect eWild = EffectInsane();

effect eLink = EffectLinkEffects(eHaste, eHitPt);

eLink = EffectLinkEffects(eLink, eWild);



ActiveWereWolf(oSelf);



ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oSelf, TurnsToSeconds(nDuration));

}



}//main

#5
Guest_ElfinMad_*

Guest_ElfinMad_*
  • Guests
I don't follow your logic at all, how does putting a DetermineCombatRound in fix it?



Like I suggested before, there could be occassions when you call GetNextObjectInShape twice in your first script. Now I'm just speculating here but what will happen if you get the next object after OBJECT_INVALID? Will you get OBJECT_INVALID again? Or does the iterator reset and you will get the first object (infinite loop)? Or will you just crash the game?

#6
Shallina

Shallina
  • Members
  • 1 011 messages
The only thing fancy I see on your script is this one :GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lSelf, TRUE, OBJECT_TYPE_CREATURE);

Perhaps you should do a tag_array for each creature in the area and get your object with the GetObjectByTag function.

//creature_1 creature_2
int i = 1;
string Tag= creature_1;
oTarget = GetObjectByTag(Tag);
while GetIsObjectValid(oTarget){
Tag = "creature_"+ IntToString(i);
oTarget = GetObjectByTag(Tag);
//your stuff;
}


you could try to do something like that, those function don't cost much processing power.

Modifié par Shallina, 20 juillet 2010 - 08:52 .


#7
Morbane

Morbane
  • Members
  • 1 883 messages
@ElfinMad - it works now - that is the only kind of logic that matters - i only call nextobject once - plus the enemy iterator - no prob now  

@Shallina - it needs to be usefull in any area so i dont think your tag idea would help

B)

Modifié par Morbane, 20 juillet 2010 - 10:08 .


#8
.Lv

.Lv
  • Members
  • 6 messages
I'm nearly sure your script will run faster if you use GetNearestCreature instead of GetNextObjectInShape. Then you can just check if the nearest creature is in the sphere (GetDistanceBetween < radius).



I don't remember where I saw that GetNearestCreature is faster though...

#9
Morbane

Morbane
  • Members
  • 1 883 messages
No worries .Lv - I found a function that removes the need for a while loop - or a GetNextInShape - it is called CheckEnemyGroupingOnTarget(object, float); it works great.



Thx though.

#10
Morbane

Morbane
  • Members
  • 1 883 messages
Turns out that the NPC I was using was the cause of my grief - when I changed to another Creature type the freezing stopped - but now I have a hyper-streamlined HeartBeat script for my persistent Feat; "Uncontrolled Rage"

YAY!