• Welcome to Battlezone Universe.
 

News:

Welcome to the BZU Archive dated December 24, 2009. Topics and posts are in read-only mode. Those with accounts will be able to login and browse anything the account had access granted to at the time. No changes to permissions will be made to be given access to particular content. If you have any questions, please reach out to squirrelof09/Rapazzini.

Main Menu

Spinoff: Uncle Avatar's Scriptor, C++ and Python Time...

Started by General BlackDragon, April 24, 2008, 12:03:45 AM

Previous topic - Next topic

OvermindDL1

The GetODFString last param requires a char*, which an std:string cannot be cast to, reason is that it will modify the string and std::string's are immutable.  So do something like "char tempChar[65];" (be sure to memset it all to zero first) and after the call to GetODFString where tempChar is full of data, then just stuff the tempChar data into your string like "tmpHolder.loopName = tempChar".

Also, in your structure, your std::string should *NOT* be a pointer (change std::string *loopName; into std::string loopName; in other words).

For SetAnimation, that is a bug in the interface for BZ2 that cannot be easily changed now, to work around it do this on that line instead:  SetAnimation(iter1->loopObject, (char*)(iter1->loopName.c_str()),iter1->loopMode);

As for the two list error's, instead of doing std::list<loopQueue>::iterator, it should be std::list<loopQueue>::const_iterator I think...  Can't check right now to be sure.

Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


Nielk1

Making it a const_iterator prevents lines like:
--(iter1->loopTime);
from working.

I was using the wrong function, I should have used erase rather than remove.
I got it to compile, I fixed the accidental string point, finally got it to accept a char array (it wouldn't before) and used you casting line. I will test it later.

EDIT: Now it AVs.

h
//To use, place in header:
//#include "..\Shared\LoopAnimator.h"
//private:
// LoopAnimator m_LoopAnimator;
//
//Place the following in the end of the constructor
//m_LoopAnimator.shareTPS(m_GameTPS)

//in execute call:
//m_LoopAnimator.execute()
//in addObject call:
//m_LoopAnimator.addObject(h)
//and so on

#ifndef _LoopAnimator_
#define _LoopAnimator_

# pragma once

#include "..\..\source\fun3d\ScriptUtils.h"
#include <vector>
#include <list>

class LoopAnimator {

unsigned int m_GameTPS; // How many turns per second there are (10, 15, 20, or 30)

int i_first,
i_last;

Handle h_first,
h_last;

bool b_first,
b_last;

float f_first,
f_last;

struct loopQueue {
Handle loopObject;
std::string loopName;
float loopTime;
bool loopMode;
};

std::list<loopQueue> waitingLoops;

bool *b_array;
int b_count;

float *f_array;
int f_count;

int *h_array;
int h_count;

int *i_array;
int i_count;

public:
LoopAnimator(void);
void shareTPS(int inTPS);
virtual bool Save(bool missionSave);
virtual bool Load(bool missionSave);
virtual bool PostLoad(bool missionSave);
virtual void AddObject(Handle h);
virtual void DeleteObject(Handle h);
virtual void Execute(void);
};
#endif


cpp
#include "LoopAnimator.h"
#include <string.h>
#include <list> //tmp

LoopAnimator::LoopAnimator(void)
{
b_count = &b_last - &b_first - 1;
b_array = &b_first + 1;

f_count = &f_last - &f_first - 1;
f_array = &f_first + 1;

    h_count = &h_last - &h_first - 1;
h_array = &h_first + 1;

i_count = &i_last - &i_first - 1;
i_array = &i_first + 1;
}

void LoopAnimator::shareTPS(int inTPS)
{
m_GameTPS = inTPS;
}

bool LoopAnimator::Load(bool missionSave)
{
if (missionSave) {
int i;

// init bools
if((b_array) && (b_count))
for (i = 0; i < b_count; i++)
b_array[i] = false;

// init floats
if((f_array) && (f_count))
for (i = 0; i < f_count; i++)
f_array[i] = 0.0f;

// init handles
if((h_array) && (h_count))
for (i = 0; i < h_count; i++)
h_array[i] = 0;

// init ints
if((i_array) && (i_count))
for (i = 0; i < i_count; i++)
i_array[i] = 0;

return true;
}

bool ret = true;

// bools
if (b_array != NULL)
Read(b_array, b_count);

// floats
if (f_array != NULL)
Read(f_array, f_count);

// Handles
if (h_array != NULL)
Read(h_array, h_count);

// ints
if (i_array != NULL)
Read(i_array, i_count);

return ret;
}

bool LoopAnimator::PostLoad(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

ConvertHandles(h_array, h_count);

return ret;
}

bool LoopAnimator::Save(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

// bools
if (b_array != NULL)
Write(b_array, b_count);

// floats
if (f_array != NULL)
Write(f_array, f_count);

// Handles
if (h_array != NULL)
Write(h_array, h_count);

// ints
if (i_array != NULL)
Write(i_array, i_count);

return ret;
}

void LoopAnimator::AddObject(Handle h)
{
// Start Queue Loop Animation
char ODFName[64];
if(GetObjInfo(h, Get_CFG, ODFName)) //is a game object check (double duty to ODFName)
{
GetObjInfo(h, Get_ODF, ODFName);
//char *loopAnimationName = new char[64];
//float loopAnimationDelay;
//bool loopAnimationType;
loopQueue tmpHolder;
tmpHolder.loopObject = h;
OpenODF(ODFName);
char loopAnimationName[64];
GetODFString(ODFName, "GameObjectClass", "loopAnimationName", 64, &loopAnimationName[64]);//tmpHolder.loopName);
tmpHolder.loopName = loopAnimationName[64];
GetODFFloat(ODFName, "GameObjectClass", "loopAnimationDelay", &tmpHolder.loopTime);
GetODFBool(ODFName, "GameObjectClass", "loopAnimationType", &tmpHolder.loopMode);
CloseODF(ODFName);
tmpHolder.loopTime *= m_GameTPS;
if((!(tmpHolder.loopName.empty())) && (tmpHolder.loopTime >= 0))// not null
{
waitingLoops.push_back(tmpHolder);
}
}
// End Queue Loop Animation
}

void LoopAnimator::DeleteObject(Handle h)
{

}

void LoopAnimator::Execute()
{
// Start Loop Animation
std::list<loopQueue>::iterator/*const_iterator*/ iter1 = waitingLoops.begin();
while( iter1 != waitingLoops.end() )
{
//AV here?
if(IsAlive2(iter1->loopObject))
{
--(iter1->loopTime);
if((iter1->loopTime) < 0)
{
SetAnimation(iter1->loopObject,(char*)(iter1->loopName.c_str()),iter1->loopMode);
StartAnimation(iter1->loopObject);
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1);
}
}else{
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1);
}
iter1++;
}   
// End Loop Animation
}


AV
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7471   |---- Battlezone II Log File ----
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7480   |//=====================================================
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7488   |App version: Patch 1.31.3pb4rc1 EDITOR May 13 2008 21:42:32
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7497   |Exception code: C0000005 (ACCESS VIOLATION) READING from 00000008h
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7505   |Message :  Exception
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7513   |Error occurred at 5/19/2008 16:11:44.
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7521   |C:\Program Files\Battlezone II 1_3pb4rc1\BZ2Edit.exe, run by Compaq_Administrator.
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7530   |1 processor(s), type 586.
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7538   |Process Memory :   1787 MB free out of   2048 MB total
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7547   |Physical memory:    114 MB free out of   1023 MB total
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7555   |Page(swap) file:   1124 MB free out of   2461 MB total
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7563   |Fault address:  0D7B30C4 01:000020C4 C:\Program Files\Battlezone II 1_3pb4rc1\missions\instantEditor.dll
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7572   |
Registers:
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7580   |EAX:00000008
EBX:052C50B8
ECX:00000000
EDX:000B0000
ESI:0229FAF0
EDI:0229FB08
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7588   |CS:EIP:001B:0D7B30C4
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7596   |SS:ESP:0023:0229FAE0  EBP:0229FB10
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7605   |DS:0023  ES:0023  FS:003B  GS:0000
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7613   |Flags:00210202
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7622   |
Call stack:
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7630   |Address   Return    Function            SourceFile
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7640   |0D7B30C4  00000000  00401867  LoopAnimator::Execute+0x00000045    d:\battlezone\dlls\bz2_1.3pb4rc1_dllsource\missions\shared\loopanimator.cpp line 152
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7647   |00401867  00000000  00401EE5  AiMission::Update+0x0000021B
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:42|7655   |00401EE5  00000000  0047028C  AI_Update+0x00000006
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7664   |0047028C  00000000  00470E07  MoveOneTurn+0x00000109
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7672   |00470E07  00000000  00585DEA  MissionHandler::State::RunState::Process+0x000003BE
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7680   |00585DEA  00000000  0046E6F7  RunCodes::Process+0x0000019F
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7689   |0046E6F7  00000000  00585DEA  MissionHandler::Process+0x00000011
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7697   |00585DEA  00000000  00585EF2  RunCodes::Process+0x0000019F
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7706   |00585EF2  00000000  00459F1C  Main::MessagePump+0x0000004A
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7713   |00459F1C  00000000  00459C5E  HandledMain+0x000003EC
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7722   |00459C5E  00000000  0045778F  HandledMain+0x0000012E
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7730   |0045778F  00000000  005969F7  WinMain+0x00000059
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7739   |005969F7  00000000  7C816FD7  memset+0x00000191
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7747   |7C816FD7  00000000  00000000  RegisterWaitForInputIdle+0x00000049
ERR |GLOBAL          |    ExceptionHandler:242  |16:11:43|7755   |

Click on the image...

OvermindDL1

Most likely it is deleting something using the erase member, which then of course invalidates the iterator, then you increase it to the next, which, since being invalid then, is now going to possibly deallocated memory.  Queue up what you want to delete and delete it later or something, a flag on each struct would work perfect for that.

Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


Nielk1

That is why I don't like iterators.

I might just make my own list struct node and use that, so I can directly access the next node and use simple pointer redirection to remove items from the list. To make another loop though all the elements in yet another way is a bit redundant; why not make the first loop use that system?

What would you suggest instead of iteration, or is my struct node a better idea?

Click on the image...

Red Devil

Is there a RemoveObject in the AddObject function?
What box???

Nielk1

I GOT IT!

I had to increment the iterator and pass in the old value.

And RD, this code is actually a separate file called by the main DLL, its function names are only the same for convenience.

Now the code isn't setting the animation name correctly, so I am going to have to check that variable at various locations to see where it goes wrong. With luck this module will be ready for use for anyone who can use bare C++.

EDIT: Found the issue, and the issue I had for so long. I, by accident, this time passed in the last latter of the char array. Before I was trying to pass in the whole array. So now, I know to pass in the first letter of the array, and let the code 'dump' the rest of the letters into the adjacent memory that is also part of the array! I still store it as a string for memory saving purposes, but the code works!

EDIT2:
Here is the code. If it checks out with you OM, I will zip it up and put it on my forum in the DLL section and link it here for anyone to use. I like this style of programming, whith multiple classes for different functions.

H file
//To use, place in header:
//#include "..\Shared\LoopAnimator.h"
//private:
// LoopAnimator m_LoopAnimator;
//
//Place the following in the end of the constructor
//m_LoopAnimator.shareTPS(m_GameTPS)

//in execute call:
//m_LoopAnimator.execute()
//in addObject call:
//m_LoopAnimator.addObject(h)
//and so on

#ifndef _LoopAnimator_
#define _LoopAnimator_

# pragma once

#include "..\..\source\fun3d\ScriptUtils.h"
#include <vector>
#include <list>

class LoopAnimator {

unsigned int m_GameTPS; // How many turns per second there are (10, 15, 20, or 30)

int i_first,
i_last;

Handle h_first,
h_last;

bool b_first,
b_last;

float f_first,
f_last;

struct loopQueue {
Handle loopObject;
std::string loopName;
//char loopName[64];
float loopTime;
bool loopMode;
};

std::list<loopQueue> waitingLoops;

bool *b_array;
int b_count;

float *f_array;
int f_count;

int *h_array;
int h_count;

int *i_array;
int i_count;

public:
LoopAnimator(void);
void shareTPS(int inTPS);
virtual bool Save(bool missionSave);
virtual bool Load(bool missionSave);
virtual bool PostLoad(bool missionSave);
virtual void AddObject(Handle h);
virtual void DeleteObject(Handle h);
virtual void Execute(void);
};
#endif


CPP file
#include "LoopAnimator.h"
#include <string.h>
#include <list> //tmp

LoopAnimator::LoopAnimator(void)
{
b_count = &b_last - &b_first - 1;
b_array = &b_first + 1;

f_count = &f_last - &f_first - 1;
f_array = &f_first + 1;

    h_count = &h_last - &h_first - 1;
h_array = &h_first + 1;

i_count = &i_last - &i_first - 1;
i_array = &i_first + 1;
}

void LoopAnimator::shareTPS(int inTPS)
{
m_GameTPS = inTPS;
}

bool LoopAnimator::Load(bool missionSave)
{
if (missionSave) {
int i;

// init bools
if((b_array) && (b_count))
for (i = 0; i < b_count; i++)
b_array[i] = false;

// init floats
if((f_array) && (f_count))
for (i = 0; i < f_count; i++)
f_array[i] = 0.0f;

// init handles
if((h_array) && (h_count))
for (i = 0; i < h_count; i++)
h_array[i] = 0;

// init ints
if((i_array) && (i_count))
for (i = 0; i < i_count; i++)
i_array[i] = 0;

return true;
}

bool ret = true;

// bools
if (b_array != NULL)
Read(b_array, b_count);

// floats
if (f_array != NULL)
Read(f_array, f_count);

// Handles
if (h_array != NULL)
Read(h_array, h_count);

// ints
if (i_array != NULL)
Read(i_array, i_count);

return ret;
}

bool LoopAnimator::PostLoad(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

ConvertHandles(h_array, h_count);

return ret;
}

bool LoopAnimator::Save(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

// bools
if (b_array != NULL)
Write(b_array, b_count);

// floats
if (f_array != NULL)
Write(f_array, f_count);

// Handles
if (h_array != NULL)
Write(h_array, h_count);

// ints
if (i_array != NULL)
Write(i_array, i_count);

return ret;
}

void LoopAnimator::AddObject(Handle h)
{
// Start Queue Loop Animation
char ODFName[64];
if(GetObjInfo(h, Get_CFG, ODFName)) //is a game object check (double duty to ODFName)
{
GetObjInfo(h, Get_ODF, ODFName);
//char *loopAnimationName = new char[64];
//float loopAnimationDelay;
//bool loopAnimationType;
loopQueue tmpHolder;
tmpHolder.loopObject = h;
OpenODF(ODFName);
char loopAnimationName[64];
GetODFString(ODFName, "GameObjectClass", "loopAnimationName", 64, &loopAnimationName[0]);//causes the code to dump into the adjacent memory, which happens to be part of the array. This consuzed me for so long
tmpHolder.loopName = loopAnimationName;
//GetODFString(ODFName, "GameObjectClass", "loopAnimationName", 64, &tmpHolder.loopName[0]);
GetODFFloat(ODFName, "GameObjectClass", "loopAnimationDelay", &tmpHolder.loopTime);
GetODFBool(ODFName, "GameObjectClass", "loopAnimationType", &tmpHolder.loopMode);
CloseODF(ODFName);
tmpHolder.loopTime *= m_GameTPS;
if((!(tmpHolder.loopName.empty())) && (tmpHolder.loopTime >= 0))// not null
{
waitingLoops.push_back(tmpHolder);
}
}
// End Queue Loop Animation
}

void LoopAnimator::DeleteObject(Handle h)
{

}

void LoopAnimator::Execute()
{
// Start Loop Animation
std::list<loopQueue>::iterator/*const_iterator*/ iter1 = waitingLoops.begin();
while( iter1 != waitingLoops.end() )
{
//AV here?
if(IsAlive2(iter1->loopObject))
{
--(iter1->loopTime);
if((iter1->loopTime) < 0)
{
SetAnimation(iter1->loopObject,(char*)(iter1->loopName.c_str()),iter1->loopMode);
StartAnimation(iter1->loopObject);
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1++); //avoid invalidation by iterating the iterator but using the old value
}else{
iter1++;
}
}else{
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1++);
}
//iter1++;
}   
// End Loop Animation
}

Click on the image...

OvermindDL1

#66
You should default the m_GameTPS to ten, just in-case a user forgets to call the function (or, as stated before, make the constructor require it...).  You have a lot of unused things in there, but they would not really harm anything.  However, you are not Save/Load'ing your list data, without that then your world will not stay synced across computers (your code is not multiplayer compatible in other words).

Your char array's you should have be one more in length then you will actually use (make it 65 instead of 64 for example), and be certain to memset it all to zero (example:  memset(ODFName, 0, sizeof(ODFName));).  Do that to all of your char array's that you have.

Can look more later, those are just the immediate obvious things I see on a quick scroll through the code box.

Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


Nielk1


Click on the image...

OvermindDL1

In save first put an integer of how big your list is, then serialize out each list element, for the string you will again but an integer of the length, then serialize out each character individually (there is a better way to do it, as I do in my python scriptor, but this is easier to understand).  Do the same thing in load but replace the saves with loads.  It is a very usual method of serializing things, you should learn it and get used to it, my programs use that style heavily (with 'prettier' syntax sugar and more caching, but still). :)

Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


Nielk1

I was trying to look at the stock code again, and I think I see another fancy use of C++'s memory allocation at work here. Since all the ints are defined in a row, they faked an array by saying the first element was the start of the array. Since its all sequential, it all works. My question is, what prevents some random memory from getting in the way and the program skipping over it when making the ints but not when reading?

EDIT:

This has a ton of issues. I might need someone else to do this part so I have something to base my later DLLs off of.
bool LoopAnimator::PostLoad(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

if(!waitingLoops.empty())
{
int sizeL = waitingLoops.size();
Handle loopObjects[sizeL];
std::list<loopQueue>::iterator iter1 = waitingLoops.begin();
int curPos = 0;
while( iter1 != waitingLoops.end() )
{
loopObjects[curPos] = iter1->loopObject;
curPos++;
iter1++;
}
ConvertHandles(loopObjects, sizeL);
}
return ret;
}

bool LoopAnimator::Save(bool missionSave)
{
if (missionSave)
return true;

bool ret = true;

if(!waitingLoops.empty())
{
int sizeL = waitingLoops.size();
Handle loopObjects[sizeL];
//std::string loopName;
float loopTimes[sizeL];
bool loopModes[sizeL];
std::list<loopQueue>::iterator iter1 = waitingLoops.begin();
int curPos = 0;
Write(sizeL,1);//will grab this to know how many strings ahead
while( iter1 != waitingLoops.end() )
{
loopObjects[curPos] = iter1->loopObject;
loopTimes[curPos] = iter1->loopTime;
loopModes[curPos] = iter1->loopMode;
Write((char*)(iter1->loopName.c_str()),(iter1->loopName.size()));
curPos++;
iter1++;
}
Write(loopObjects, sizeL);
Write(loopTimes, sizeL);
Write(loopModes, sizeL);
}
return ret;
}

Click on the image...

OvermindDL1

Memory in classes is defined in the order that it appears, ergo nothing will end up 'between' things. :)

From a quick looksee (assuming waitingLoops is the only thing you need to save, you don't need your gametps stuff too?) I see at least one bug.  Your Handle loopObjects[sizeL]; array will not compile, don't bother with an array and just pass each Handle individually (passing in 1 as the number of elements parameter of course) to the ConvertHandles function.
Hmm, ditto with your array declarations of your timer and all such, let me type of something real quick (no say if this works, I am typing it out in this little posting quick window, but the thinking is right, also you forgot a Load function):
bool LoopAnimator::PostLoad(bool missionSave)
{
if (missionSave)
return true;

foreach(yourWaitingLoopsStruct &s, waitingLoops)
{
ConvertHandles(s.loopObject, 1);
}
return true;
}

bool LoopAnimator::Load(bool missionSave)
{
if (missionSave)
return true;

// Make sure to clear your waitingLoops first, it might not be in a Load function...
waitingLoops.clear(); // Or whatever the call was...

int size;
Read(&size, 1); // Don't forget the & for absolute values like this in both read and write, remember, it operates on memory, not values
waitingLoops.resize(size)
foreach(yourWaitingLoopsStruct &s, waitingLoops) // This is something in my code, you can figure out what it does, yes it compiles fine on my pc...
{
Read(&(s.loopObject), 1);
Read(&(s.loopTime), 1);
Read(&(s.loopMode), 1);
int strSize;
Read(&strSize, 1);
char *tempStr = new char[strSize+1]; // Could do char tempStr[1024], possible buffer overflow, but can you even have a string that long in a bz2 odf anyway?, would be a lot faster in execution though...
memset(tempStr, 0, strSize+1); // sizeof() will not work in these cases, sizeof is compile-time, not run-time
Read((void*)tempStr, strSize);
s.loopName = std::string(tempStr);
delete [] tempStr;
}

return true;
}

bool LoopAnimator::Save(bool missionSave)
{
if (missionSave)
return true;

int size = waitingLoops.size();
Write(&size, 1); // Don't forget the & for absolute values like this in both read and write, remember, it operates on memory, not values
foreach(yourWaitingLoopsStruct &s, waitingLoops) // This is something in my code, you can figure out what it does, yes it compiles fine on my pc...
{
Write(&(s.loopObject), 1);
Write(&(s.loopTime), 1);
Write(&(s.loopMode), 1);
int strSize = s.loopName.size();
Write(&strSize, 1);
Write((void*)s.loopName.c_str(), strSize);
}

return true;
}


Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


Nielk1

I hadn't done the load function yet because I was having so much trouble.
I'm learning a lot about the way C++ uses memory addresses and all that now, so this is a big help for all of my future programming.

foreach loop eh? For each Struct in my List. I keep calling it forevery, which is wrong and doesn't compile, which is why I don' use those much.

I will try your code, or use it as a base at least, in a few hours and post my results and modifications for review. If it finally looks right I will test it when I find someone willing.

I forgot about the TPS cause I was rather annoyed the way I had to move it in in the first place.

I need to find a notebook and jot some of these things down (order of memory, automatically filling the values so first and last work, and iterating the iterator in the erase function call.

EDIT:
I had to change the foreach to get it to work (perhaspe yours was a boost foreach):
for each(loopQueue &s in waitingLoops)
but it still doesnt like the &s so I used s.

Does saving in single player to a file use these function, or are they only used in saving the state of the server's game for a new client? I ask because a saved game files does not work corectly how I have it now.

EDIT2:
I was never calling my 2nd Classe's load and save functions from the main body. DOIY!

EDIT3:
I did a quick test and the values are garbage data during the post load. What did I do wrong?

H
//To use, place in header:
//#include "..\Shared\LoopAnimator.h"
//private:
// LoopAnimator m_LoopAnimator;
//
//Place the following in the end of the constructor
//m_LoopAnimator.shareTPS(m_GameTPS)

//in execute call:
//m_LoopAnimator.execute()
//in addObject call:
//m_LoopAnimator.addObject(h)
//and so on
//
//be sure to call the same, load, and post load functions int he base DLL class at the end of those functions

#ifndef _LoopAnimator_
#define _LoopAnimator_

# pragma once

#include "..\..\source\fun3d\ScriptUtils.h"
#include <vector>
#include <list>

class LoopAnimator {

unsigned int m_GameTPS; // How many turns per second there are (10, 15, 20, or 30)

struct loopQueue {
Handle loopObject;
std::string loopName;
//char loopName[64];
float loopTime;
bool loopMode;
};

std::list<loopQueue> waitingLoops;

public:
LoopAnimator(void);
void shareTPS(int inTPS);
virtual bool Save(bool missionSave);
virtual bool Load(bool missionSave);
virtual bool PostLoad(bool missionSave);
virtual void AddObject(Handle h);
virtual void DeleteObject(Handle h);
virtual void Execute(void);
};
#endif


CPP
#include "LoopAnimator.h"
#include <string.h>
#include <list> //tmp

LoopAnimator::LoopAnimator(void)
{
m_GameTPS = 10; //default
}

void LoopAnimator::shareTPS(int inTPS)
{
m_GameTPS = inTPS;
}

bool LoopAnimator::PostLoad(bool missionSave)
{
if (missionSave)
return true;

char TempMsgStr[1024];

for each(loopQueue s in waitingLoops)//for each(loopQueue &s in waitingLoops)
{
sprintf_s(TempMsgStr, "B- Handle: %08X Name: %s Time: %d", s.loopObject, s.loopName, s.loopTime);
PrintConsoleMessage(TempMsgStr);
ConvertHandles(&(s.loopObject), 1);//ConvertHandles(&s.loopObject, 1);
sprintf_s(TempMsgStr, "A- Handle: %08X Name: %s Time: %d", s.loopObject, s.loopName, s.loopTime);
PrintConsoleMessage(TempMsgStr);
}
return true;
}

bool LoopAnimator::Load(bool missionSave)
{
if (missionSave)
return true;

// Make sure to clear your waitingLoops first, it might not be in a Load function...
waitingLoops.clear(); // Or whatever the call was...

int size;
Read(&size, 1); // Don't forget the & for absolute values like this in both read and write, remember, it operates on memory, not values
waitingLoops.resize(size);
for each(loopQueue s in waitingLoops)
{
Read(&(s.loopObject), 1);
Read(&(s.loopTime), 1);
Read(&(s.loopMode), 1);
int strSize;
Read(&strSize, 1);
char *tempStr = new char[strSize+1]; // Could do char tempStr[1024], possible buffer overflow, but can you even have a string that long in a bz2 odf anyway?, would be a lot faster in execution though...
memset(tempStr, 0, strSize+1); // sizeof() will not work in these cases, sizeof is compile-time, not run-time
Read((void*)tempStr, strSize);
s.loopName = std::string(tempStr);
delete [] tempStr;
}
Read(&m_GameTPS,1);

return true;
}

bool LoopAnimator::Save(bool missionSave)
{
if (missionSave)
return true;

int size = waitingLoops.size();
Write(&size, 1); // Don't forget the & for absolute values like this in both read and write, remember, it operates on memory, not values
for each(loopQueue s in waitingLoops) // This is something in my code, you can figure out what it does, yes it compiles fine on my pc...
{
Write(&(s.loopObject), 1);
Write(&(s.loopTime), 1);
Write(&(s.loopMode), 1);
int strSize = s.loopName.size();
Write(&strSize, 1);
Write((void*)s.loopName.c_str(), strSize);
}
Write(&m_GameTPS,1);

return true;
}

void LoopAnimator::AddObject(Handle h)
{
// Start Queue Loop Animation
char ODFName[64];
memset(ODFName, 0, sizeof(ODFName));//do this to all char arrays for bz2
if(GetObjInfo(h, Get_CFG, ODFName)) //is a game object check (double duty to ODFName)
{
GetObjInfo(h, Get_ODF, ODFName);
//char *loopAnimationName = new char[64];
//float loopAnimationDelay;
//bool loopAnimationType;
loopQueue tmpHolder;
tmpHolder.loopObject = h;
OpenODF(ODFName);
char loopAnimationName[65]; //one more in length
memset(loopAnimationName, 0, sizeof(loopAnimationName));//do this to all char arrays for bz2
GetODFString(ODFName, "GameObjectClass", "loopAnimationName", 64, &loopAnimationName[0]);//causes the code to dump into the adjacent memory, which happens to be part of the array. This consuzed me for so long
tmpHolder.loopName = loopAnimationName;
//GetODFString(ODFName, "GameObjectClass", "loopAnimationName", 64, &tmpHolder.loopName[0]);
GetODFFloat(ODFName, "GameObjectClass", "loopAnimationDelay", &tmpHolder.loopTime);
GetODFBool(ODFName, "GameObjectClass", "loopAnimationType", &tmpHolder.loopMode);
CloseODF(ODFName);
tmpHolder.loopTime *= m_GameTPS;
if((!(tmpHolder.loopName.empty())) && (tmpHolder.loopTime >= 0))// not null
{
waitingLoops.push_back(tmpHolder);
}
}
// End Queue Loop Animation
}

void LoopAnimator::DeleteObject(Handle h)
{
//cleanup is handled in execute loop
}

void LoopAnimator::Execute()
{
// Start Loop Animation
std::list<loopQueue>::iterator/*const_iterator*/ iter1 = waitingLoops.begin();
while( iter1 != waitingLoops.end() )
{
if(IsAlive2(iter1->loopObject))
{
--(iter1->loopTime);
if((iter1->loopTime) < 0)
{
SetAnimation(iter1->loopObject,(char*)(iter1->loopName.c_str()),iter1->loopMode);
StartAnimation(iter1->loopObject);
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1++); //avoid invalidation by iterating the iterator but using the old value
}else{
iter1++;
}
}else{
//waitingLoops.remove(iter1);
waitingLoops.erase(iter1++);
}
//iter1++;
}   
// End Loop Animation
}

Click on the image...

OvermindDL1

Mine should be correct, and yes, my foreach is BOOST_FOREACH, so if you have boost installed (as I keep recommending :) ) then your for iteration loops can become a whole lot more simple using that.

Your "for each(..." thing is no where near C++, some other language, python it looks like? :P

And yes, saving/loading singleplayer uses these functions, as well as multiplayer to keep things synced.

As for memory in C/C++, it does it just like assembler, which is just how the hardware does it, no wierd abstraction layers like the crap Java adds on top, this is as basic as it gets, try not to make it too complex in your mind and it becomes very simple. :)

Generated by OvermindDL1's Signature Auto-Add Script via GreaseMonkey


lucky_foot

<sidetracked comment>

One of these days I'm going to be able to understand this thread. :D

</sidetracked comment>
Jonathan S.



Nielk1

This is the for each I am using:

http://blogs.msdn.com/arich/archive/2004/09/08/227139.aspx

I will keep probing the load and save functions since they appear to be failing.

Click on the image...