/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//////////////////////////////////////////////////////////////////////////////////////
// @@ @@@ @@@ @@ @@@@@ //
// @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ //
// @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ //
// @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ //
// @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ //
// @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ //
// @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ //
// @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ //
// @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ //
// @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ //
// @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ //
//@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ //
//@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ //
//@@@ @@@ @@@ @@@@@ @@ @@@ //
// @@@ @@@ @@ @@ STUDIOS //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// ARX_ChangeLevel
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Change Level
//
// Updates: (date) (person) (update)
//
// Code: Cyril Meynier
//
// Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
// TODO:
// -Need to save GlobalMods for each level
// -Need to restore Player inventory...
// -Player inventory Items Must be pushed but Mustn't be in ANY Level Index...
// -IO Tweaks ?
// -Check Spawned Objects Ident... Might be dangerous
//
//////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "ARX_ChangeLevel.h"
#include "ARX_Damages.h"
#include "ARX_Equipment.h"
#include "ARX_Interactive.h"
#include "ARX_Minimap.h"
#include "ARX_NPC.h"
#include "ARX_Particles.h"
#include "ARX_Paths.h"
#include "ARX_Sound.h"
#include "ARX_Speech.h"
#include "ARX_Spells.h"
#include "ARX_time.h"
#include
#include
#include
#include
#define _CRTDBG_MAP_ALLOC
#include
#define new new(_NORMAL_BLOCK,__FILE__, __LINE__)
extern INTERACTIVE_OBJ * CURRENT_TORCH;
extern long GLOBAL_MAGIC_MODE;
float FORCE_TIME_RESTORE = 0;
extern EERIE_3D WILL_RESTORE_PLAYER_POSITION;
extern long WILL_RESTORE_PLAYER_POSITION_FLAG;
extern long NO_GMOD_RESET;
void DANAE_ReleaseAllDatasDynamic();
//-----------------------------------------------------------------------------
#define TYPE_NPC 1
#define TYPE_ITEM 2
#define TYPE_FIX 3
#define TYPE_CAMERA 4
#define TYPE_MARKER 5
//-----------------------------------------------------------------------------
extern long ARX_CONVERSATION;
extern HANDLE LIGHTTHREAD;
extern float PROGRESS_BAR_COUNT;
extern float OLD_PROGRESS_BAR_COUNT;
extern float PROGRESS_BAR_TOTAL;
extern long NO_PLAYER_POSITION_RESET;
extern INTERACTIVE_OBJ * CAMERACONTROLLER;
extern float InventoryDir;
extern char LOCAL_SAVENAME[64];
extern long HERO_SHOW_1ST;
extern long EXTERNALVIEW;
extern long LOAD_N_DONT_ERASE;
extern long DONT_LOAD_INTERS;
extern long FORCE_IO_INDEX;
extern long FORBID_SCRIPT_IO_CREATION;
extern long NO_TIME_INIT;
extern long RELOADING;
extern long CHANGE_LEVEL_ICON;
extern long FOR_EXTERNAL_PEOPLE;
extern long TRUE_PLAYER_MOUSELOOK_ON;
extern int iTimeToDrawD7;
extern EERIE_3D LastValidPlayerPos;
#define MAX_IO_SAVELOAD 1500
//-----------------------------------------------------------------------------
typedef struct
{
char ident[64];
} TEMP_IO;
TEMP_IO * tio = NULL;
long nb_tio = 0;
long NEW_LEVEL = -1;
long LAST_CHINSTANCE = 1; // temporary MUST return to -1;
char CurGamePath[256];
float ARX_CHANGELEVEL_DesiredTime = 0;
long CONVERT_CREATED = 0;
long DONT_WANT_PLAYER_INZONE = 0;
long FORBID_SAVE = 0;
long _FIRSTTIME = 0;
CSaveBlock * _pSaveBlock = NULL;
ARX_CHANGELEVEL_IO_INDEX * idx_io = NULL;
long idx_io_nb = 0;
ARX_CHANGELEVEL_VARIABLE_SAVE * index_variable = NULL;
ARX_CHANGELEVEL_INVENTORY_DATA_SAVE ** _Gaids = NULL;
char * StdBuffer = NULL;
long StdBuffer_size = 0;
char * GetStdBuffer(long size)
{
if (size > StdBuffer_size)
{
StdBuffer = (char *)realloc(StdBuffer, size);
StdBuffer_size = size;
}
return(StdBuffer);
}
void FreeStdBuffer()
{
if (StdBuffer)
free(StdBuffer);
StdBuffer = NULL;
StdBuffer_size = 0;
}
extern long ARX_CONVERSATION;
extern HANDLE LIGHTTHREAD;
extern INTERACTIVE_OBJ * CAMERACONTROLLER;
extern EERIE_BACKGROUND bkrgnd;
long CURRENT_GAME_INSTANCE = -1;
char GameSavePath[256];
extern char LOCAL_SAVENAME[64];
void ARX_GAMESAVE_MakePath()
{
sprintf(GameSavePath, "%sSave%s\\", Project.workingdir, LOCAL_SAVENAME);
if (!DirectoryExist(GameSavePath))
{
CreateDirectory(GameSavePath, NULL);
}
sprintf(GameSavePath, "%sSave%s\\Save%04d\\", Project.workingdir, LOCAL_SAVENAME, CURRENT_GAME_INSTANCE);
if (!DirectoryExist(GameSavePath))
{
CreateDirectory(GameSavePath, NULL);
}
}
void ARX_GAMESAVE_CreateNewInstance()
{
char basepath[256];
char testpath[256];
long num = 1;
sprintf(basepath, "%sSave%s\\", Project.workingdir, LOCAL_SAVENAME);
while (1)
{
sprintf(testpath, "%sSave%04d", basepath, num);
if (!DirectoryExist(testpath))
{
CreateDirectory(testpath, NULL);
CURRENT_GAME_INSTANCE = num;
ARX_GAMESAVE_MakePath();
return;
}
else
{
//le directory peut exister mais peut être vide après un crash
strcat(testpath, "\\GSAVE.SAV");
FILE * f = fopen(testpath, "rb");
if (!f)
{
CURRENT_GAME_INSTANCE = num;
ARX_GAMESAVE_MakePath();
return;
}
fclose(f);
}
num++;
}
}
long NEED_LOG = 0; //1;
void LogData(char * tex)
{
if (!NEED_LOG) return;
FILE * fic;
if ((fic = fopen("c:\\ARXlog.txt", "a")) != NULL)
{
fprintf(fic, "%s\n", tex);
fclose(fic);
}
}
//-----------------------------------------------------------------------------
INTERACTIVE_OBJ * ConvertToValidIO(char * str)
{
CONVERT_CREATED = 0;
if ((!str)
|| (str[0] == 0)) return NULL;
long t = GetTargetByNameTarget(str);
if (t < 0)
{
if ((NEED_LOG) && (stricmp(str, "none")))
{
char temp[256];
sprintf(temp, "Call to ConvertToValidIO(%s)", str);
LogData(temp);
}
t = ARX_CHANGELEVEL_Pop_IO(str);
if (t < 0) return NULL;
}
inter.iobj[t]->level = (short)NEW_LEVEL; // Not really needed anymore...
return (inter.iobj[t]);
}
//-----------------------------------------------------------------------------
long GetIOAnimIdx2(INTERACTIVE_OBJ * io, ANIM_HANDLE * anim)
{
if ((!io)
|| (!anim))
return -1;
for (long i = 0; i < MAX_ANIMS; i++)
{
if (io->anims[i] == anim)
return i;
}
return -1;
}
//--------------------------------------------------------------------------------------------
void ARX_CHANGELEVEL_MakePath()
{
sprintf(CurGamePath, "%sSave%s\\", Project.workingdir, LOCAL_SAVENAME);
if (!DirectoryExist(CurGamePath))
{
CreateDirectory(CurGamePath, NULL);
}
sprintf(CurGamePath, "%sSave%s\\Cur%04d\\", Project.workingdir, LOCAL_SAVENAME, LAST_CHINSTANCE);
if (!DirectoryExist(CurGamePath))
CreateDirectory(CurGamePath, NULL);
}
//--------------------------------------------------------------------------------------------
void ARX_CHANGELEVEL_CreateNewInstance()
{
char basepath[256];
char testpath[256];
long num = 1;
sprintf(basepath, "%sSave%s\\", Project.workingdir, LOCAL_SAVENAME);
while (1)
{
sprintf(testpath, "%sCur%04d", basepath, num);
if (!DirectoryExist(testpath))
{
CreateDirectory(testpath, NULL);
LAST_CHINSTANCE = num;
ARX_CHANGELEVEL_MakePath();
return;
}
num++;
}
}
CSaveBlock * GLOBAL_pSaveB = NULL;
void ARX_Changelevel_CurGame_Open()
{
if (GLOBAL_pSaveB)
ARX_Changelevel_CurGame_Close();
char fic[256];
sprintf(fic, "%sGsave.sav", CurGamePath);
GLOBAL_pSaveB = new CSaveBlock(fic);
GLOBAL_pSaveB->BeginRead();
return;
}
bool ARX_Changelevel_CurGame_Seek(char * ident)
{
if (GLOBAL_pSaveB)
{
char fic[256];
sprintf(fic, "%s.sav", ident);
if (GLOBAL_pSaveB->ExistFile(fic)) return true;
}
return false;
}
void ARX_Changelevel_CurGame_Close()
{
if (GLOBAL_pSaveB)
{
GLOBAL_pSaveB->EndRead();
delete GLOBAL_pSaveB;
GLOBAL_pSaveB = NULL;
}
}
extern long JUST_RELOADED;
extern void DemoFileCheck();
extern long FINAL_COMMERCIAL_DEMO;
//--------------------------------------------------------------------------------------------
void ARX_CHANGELEVEL_Change(char * level, char * target, long angle, long confirm)
{
LogData("-----------------------------------");
HERMES_DATE_TIME hdt;
GetDate(&hdt);
if (NEED_LOG)
{
LogData("ARX_CHANGELEVEL_Change");
char tex[256];
sprintf(tex, "Date: %02d/%02d/%d Time: %dh%d", hdt.days, hdt.months, hdt.years, hdt.hours, hdt.mins);
LogData(tex);
sprintf(tex, "level %s target %s", level, target);
LogData(tex);
}
DemoFileCheck();
PROGRESS_BAR_TOTAL = 238;
OLD_PROGRESS_BAR_COUNT = PROGRESS_BAR_COUNT = 0;
ARX_CHANGELEVEL_DesiredTime = ARX_TIME_Get();
if (confirm)
{
if (!OKBox("Change Level ?", "CONFIRM")) return;
}
if (LAST_CHINSTANCE == -1)
{
ARX_CHANGELEVEL_CreateNewInstance();
}
else ARX_CHANGELEVEL_MakePath();
FORBID_SAVE = 1;
// CurGamePath contains current game temporary savepath
char tex[256];
sprintf(tex, "LEVEL%s", level);
long num = GetLevelNumByName(tex);
if ((FINAL_COMMERCIAL_DEMO)
&& (num != 10)
&& (num != 12)
&& (num != 15)
&& (num != 1))
return;
LoadLevelScreen(GDevice, num);
if (num == -1)
{
// fatality...
ShowPopup("Internal Non-Fatal Error");
return;
}
NEW_LEVEL = num;
// TO RESTORE !!!!!!!!!!!!
if (num == CURRENTLEVEL) // not changing level, just teleported
{
long t = GetTargetByNameTarget(target);
if (t > 0)
{
EERIE_3D pos;
if (inter.iobj[t])
if (GetItemWorldPosition(inter.iobj[t], &pos))
{
moveto.x = player.pos.x = pos.x;
moveto.y = player.pos.y = pos.y + PLAYER_BASE_HEIGHT;
moveto.z = player.pos.z = pos.z;
NO_PLAYER_POSITION_RESET = 1;
}
}
player.desiredangle.b = player.angle.b = (float)angle;
return; // nothing more to do :)
}
ARX_PLAYER_Reset_Fall();
ARX_TIME_Pause();
PROGRESS_BAR_COUNT += 1.f;
LoadLevelScreen(GDevice, num);
LogData("Before ARX_CHANGELEVEL_PushLevel");
ARX_CHANGELEVEL_PushLevel(CURRENTLEVEL, NEW_LEVEL);
LogData("After ARX_CHANGELEVEL_PushLevel");
LogData("Before ARX_CHANGELEVEL_PopLevel");
ARX_CHANGELEVEL_PopLevel(num, 1);
LogData("After ARX_CHANGELEVEL_PopLevel");
FreeStdBuffer();
// Now restore player pos to destination
long t = GetTargetByNameTarget(target);
if (t > 0)
{
EERIE_3D pos;
if (inter.iobj[t])
if (GetItemWorldPosition(inter.iobj[t], &pos))
{
moveto.x = player.pos.x = pos.x;
moveto.y = player.pos.y = pos.y + PLAYER_BASE_HEIGHT;
moveto.z = player.pos.z = pos.z;
NO_PLAYER_POSITION_RESET = 1;
Vector_Copy(&WILL_RESTORE_PLAYER_POSITION, &moveto);
WILL_RESTORE_PLAYER_POSITION_FLAG = 1;
}
}
CURRENTLEVEL = NEW_LEVEL;
player.desiredangle.b = player.angle.b = (float)angle;
DONT_WANT_PLAYER_INZONE = 1;
ARX_PLAYER_RectifyPosition();
JUST_RELOADED = 1;
NO_GMOD_RESET = 0;
LogData("-----------------------------------");
}
//--------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//// SAVING ////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------------
long ARX_CHANGELEVEL_PushLevel(long num, long newnum)
{
ARX_CHANGELEVEL_INDEX asi;
ARX_SCRIPT_EventStackExecuteAll();
// Close secondary inventory before leaving
if (SecondaryInventory != NULL)
{
INTERACTIVE_OBJ * io = (INTERACTIVE_OBJ *)SecondaryInventory->io;
if (io != NULL)
{
InventoryDir = -1;
SendIOScriptEvent(io, SM_INVENTORY2_CLOSE, "");
TSecondaryInventory = SecondaryInventory;
SecondaryInventory = NULL;
}
}
ForcePlayerInventoryObjectLevel(newnum);
char lvltxt[64];
sprintf(lvltxt, "l%03d", num);
char sfile[256];
sprintf(sfile, "%sGsave.sav", CurGamePath);
_pSaveBlock = new CSaveBlock(sfile);
if (!_pSaveBlock->BeginSave(true, 1)) return -1;
// Now we can save our things
if (ARX_CHANGELEVEL_Push_Index(&asi, num) != 1)
{
ShowPopup("Error Saving Index...");
ARX_TIME_UnPause();
return -1;
}
if (ARX_CHANGELEVEL_Push_Globals(num) != 1)
{
ShowPopup("Error Saving Globals...");
ARX_TIME_UnPause();
return -1;
}
if (ARX_CHANGELEVEL_Push_Player(num) != 1)
{
ShowPopup("Error Saving Player...");
ARX_TIME_UnPause();
return -1;
}
if (ARX_CHANGELEVEL_Push_AllIO(num) != 1)
{
ShowPopup("Error Saving IOs...");
ARX_TIME_UnPause();
return -1;
}
_pSaveBlock->EndSave();
delete _pSaveBlock;
_pSaveBlock = NULL;
ARX_TIME_UnPause();
return 1;
}
bool IsPlayerEquipedWith(INTERACTIVE_OBJ * io)
{
if (!io) return false;
long num = GetInterNum(io);
if (io == CURRENT_TORCH)
return true;
if (ValidIONum(num))
{
for (long i = 0; i < MAX_EQUIPED; i++)
{
if (player.equiped[i] == num)
{
return true;
}
}
}
return false;
}
extern GLOBAL_MODS stacked;
extern GLOBAL_MODS current;
extern GLOBAL_MODS desired;
//--------------------------------------------------------------------------------------------
long ARX_CHANGELEVEL_Push_Index(ARX_CHANGELEVEL_INDEX * asi, long num)
{
unsigned char * dat;
long pos = 0;
asi->version = ARX_GAMESAVE_VERSION;
asi->nb_inter = 0;
asi->nb_paths = nbARXpaths;
asi->time = ARX_TIME_GetUL(); //treat warning C4244 conversion from 'float' to 'unsigned long''
asi->nb_lights = 0;
memcpy(&asi->gmods_stacked, &stacked, sizeof(GLOBAL_MODS));
memcpy(&asi->gmods_desired, &desired, sizeof(GLOBAL_MODS));
memcpy(&asi->gmods_current, ¤t, sizeof(GLOBAL_MODS));
for (long i = 1; i < inter.nbmax; i++)
{
if ((inter.iobj[i] != NULL)
&& (!(inter.iobj[i]->ioflags & IO_NOSAVE))
&& (!IsInPlayerInventory(inter.iobj[i]))
&& (!IsPlayerEquipedWith(inter.iobj[i]))
)
{
asi->nb_inter++;
}
}
for (int i = 0; i < MAX_LIGHTS; i++)
{
EERIE_LIGHT * el = GLight[i];
if ((el != NULL) && (!(el->type & TYP_SPECIAL1)))
asi->nb_lights++;
}
char savefile[256];
sprintf(savefile, "lvl%03d.sav", num);
long allocsize = sizeof(ARX_CHANGELEVEL_INDEX)
+ sizeof(ARX_CHANGELEVEL_IO_INDEX) * asi->nb_inter
+ sizeof(ARX_CHANGELEVEL_PATH) * asi->nb_paths
+ sizeof(ARX_CHANGELEVEL_LIGHT) * asi->nb_lights;
+48000;
void * playlist = NULL;
unsigned long asize = 0;
ARX_SOUND_AmbianceSavePlayList(&playlist, &asize);
allocsize += asize;
retry:
;
dat = (unsigned char *)malloc(allocsize);
if (!dat)
{
if (HERMES_Memory_Emergency_Out(allocsize, "ChangeLevel_PushIndex"))
goto retry;
}
asi->ambiances_data_size = asize;
memcpy(dat, asi, sizeof(ARX_CHANGELEVEL_INDEX));
pos += sizeof(ARX_CHANGELEVEL_INDEX);
ARX_CHANGELEVEL_IO_INDEX aii;
for (int i = 1; i < inter.nbmax; i++)
{
if ((inter.iobj[i] != NULL)
&& (!(inter.iobj[i]->ioflags & IO_NOSAVE))
&& (!IsInPlayerInventory(inter.iobj[i]))
&& (!IsPlayerEquipedWith(inter.iobj[i]))
)
{
strcpy(aii.filename, inter.iobj[i]->filename);
aii.ident = inter.iobj[i]->ident;
aii.level = inter.iobj[i]->level;
aii.truelevel = inter.iobj[i]->truelevel;
aii.num = i; // !!!
aii.unused = 0;
memcpy(dat + pos, &aii, sizeof(ARX_CHANGELEVEL_IO_INDEX));
pos += sizeof(ARX_CHANGELEVEL_IO_INDEX);
}
}
ARX_CHANGELEVEL_PATH * acp;
for (int i = 0; i < nbARXpaths; i++)
{
acp = (ARX_CHANGELEVEL_PATH *)(dat + pos);
memset(acp, 0, sizeof(ARX_CHANGELEVEL_PATH));
strcpy(acp->name, ARXpaths[i]->name);
strcpy(acp->controled, ARXpaths[i]->controled);
pos += sizeof(ARX_CHANGELEVEL_PATH);
}
if (asi->ambiances_data_size > 0)
{
memcpy((char *)(dat + pos), playlist, asi->ambiances_data_size);
pos += asi->ambiances_data_size;
free(playlist);
}
for (int i = 0; i < MAX_LIGHTS; i++)
{
EERIE_LIGHT * el = GLight[i];
if ((el != NULL) && (!(el->type & TYP_SPECIAL1)))
{
ARX_CHANGELEVEL_LIGHT * acl = (ARX_CHANGELEVEL_LIGHT *)(dat + pos);
memset(acl, 0, sizeof(ARX_CHANGELEVEL_LIGHT));
acl->status = el->status;
pos += sizeof(ARX_CHANGELEVEL_LIGHT);
}
}
char * compressed = NULL;
long cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
free(dat);
for (int i = 0; i < cpr_pos; i += 2)
compressed[i] = ~compressed[i];
bool ret = _pSaveBlock->Save(savefile, compressed, cpr_pos);
free(compressed);
if (!ret) return -1;
return 1;
}
//--------------------------------------------------------------------------------------------
long ARX_CHANGELEVEL_Push_Globals(long num)
{
ARX_CHANGELEVEL_SAVE_GLOBALS acsg;
unsigned char * dat;
long pos = 0;
memset(&acsg, 0, sizeof(ARX_CHANGELEVEL_SAVE_GLOBALS));
acsg.nb_globals = NB_GLOBALS;
acsg.version = ARX_GAMESAVE_VERSION;
char savefile[256];
sprintf(savefile, "Globals.sav");
long allocsize = sizeof(ARX_VARIABLE_SAVE) * acsg.nb_globals
+ sizeof(ARX_CHANGELEVEL_SAVE_GLOBALS) + 1000
+ 48000;
retry:
;
dat = (unsigned char *)malloc(allocsize);
if (!dat)
{
if (HERMES_Memory_Emergency_Out(allocsize, "ChangeLevel_PushGlobals"))
goto retry;
}
memcpy(dat, &acsg, sizeof(ARX_CHANGELEVEL_SAVE_GLOBALS));
pos += sizeof(ARX_CHANGELEVEL_SAVE_GLOBALS);
long count;
ARX_VARIABLE_SAVE avs;
for (long i = 0; i < NB_GLOBALS; i++)
{
switch (svar[i].type)
{
case TYPE_G_TEXT:
if ((svar[i].name[0] == '$') || (svar[i].name[0] == '£'))
{
strcpy(avs.name, svar[i].name);
if (svar[i].text)
count = strlen(svar[i].text);
else
count = 0;
avs.fval = (float)count;
avs.type = TYPE_G_TEXT;
memcpy(dat + pos, &avs, sizeof(ARX_VARIABLE_SAVE));
pos += sizeof(ARX_VARIABLE_SAVE);
if (count > 0)
memcpy(dat + pos, svar[i].text, count + 1);
pos += (long)avs.fval;
}
else
acsg.nb_globals--;
break;
case TYPE_G_LONG:
if ((svar[i].name[0] == '#') || (svar[i].name[0] == '§'))
{
strcpy(avs.name, svar[i].name);
avs.fval = (float)svar[i].ival;
avs.type = TYPE_G_LONG;
memcpy(dat + pos, &avs, sizeof(ARX_VARIABLE_SAVE));
pos += sizeof(ARX_VARIABLE_SAVE);
}
else
acsg.nb_globals--;
break;
case TYPE_G_FLOAT:
if ((svar[i].name[0] == '&') || (svar[i].name[0] == '@'))
{
strcpy(avs.name, svar[i].name);
avs.fval = svar[i].fval;
avs.type = TYPE_G_FLOAT;
memcpy(dat + pos, &avs, sizeof(ARX_VARIABLE_SAVE));
pos += sizeof(ARX_VARIABLE_SAVE);
}
else
acsg.nb_globals--;
break;
default:
acsg.nb_globals--;
break;
}
}
char * compressed = NULL;
long cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
free(dat);
for (int i = 0; i < cpr_pos; i += 2)
compressed[i] = ~compressed[i];
_pSaveBlock->Save(savefile, compressed, cpr_pos);
free(compressed);
return 1;
}
//--------------------------------------------------------------------------------------------
void FillIOIdent(char * tofill, INTERACTIVE_OBJ * io)
{
if ((!io)
|| (!ValidIOAddress(io))
|| (io->filename[0] == 0)
)
strcpy(tofill, "NONE");
else
sprintf(tofill, "%s_%04d", GetName(io->filename), io->ident);
}
extern long sp_max;
extern long cur_rf;
extern long cur_mx;
extern long cur_mr;
extern long cur_pom;
extern long sp_wep;
extern long sp_arm;
//--------------------------------------------------------------------------------------------
long ARX_CHANGELEVEL_Push_Player(long num)
{
ARX_CHANGELEVEL_PLAYER * asp;
unsigned char * dat;
long allocsize = sizeof(ARX_CHANGELEVEL_PLAYER) + Keyring_Number * sizeof(KEYRING_SLOT) + 48000;
allocsize += 80 * nb_PlayerQuest;
allocsize += sizeof(ARX_CHANGELEVEL_MAPMARKER_DATA) * Nb_Mapmarkers;
retry:
;
dat = (unsigned char *) malloc(allocsize);
if (!dat)
{
if (HERMES_Memory_Emergency_Out(allocsize, "ChangeLevel_PushPlayer"))
goto retry;
}
asp = (ARX_CHANGELEVEL_PLAYER *)dat;
long pos = 0;
pos += (sizeof(ARX_CHANGELEVEL_PLAYER));
memset(asp, 0, sizeof(ARX_CHANGELEVEL_PLAYER));
asp->AimTime = player.AimTime;
asp->angle.a = player.angle.a;
asp->angle.b = player.angle.b;
asp->angle.g = player.angle.g;
asp->armor_class = player.armor_class;
asp->Attribute_Constitution = player.Attribute_Constitution;
asp->Attribute_Dexterity = player.Attribute_Dexterity;
asp->Attribute_Mind = player.Attribute_Mind;
asp->Attribute_Strength = player.Attribute_Strength;
asp->Critical_Hit = player.Critical_Hit;
asp->Current_Movement = player.Current_Movement;
asp->damages = player.damages;
asp->doingmagic = player.doingmagic;
asp->Interface = player.Interface;
asp->playerflags = player.playerflags;
if (TELEPORT_TO_LEVEL[0])
strcpy(asp->TELEPORT_TO_LEVEL, TELEPORT_TO_LEVEL);
else
memset(asp->TELEPORT_TO_LEVEL, 0, 64);
if (TELEPORT_TO_POSITION[0])
strcpy(asp->TELEPORT_TO_POSITION, TELEPORT_TO_POSITION);
else
memset(asp->TELEPORT_TO_POSITION, 0, 64);
asp->TELEPORT_TO_ANGLE = TELEPORT_TO_ANGLE;
asp->CHANGE_LEVEL_ICON = CHANGE_LEVEL_ICON;
asp->bag = player.bag;
FillIOIdent(asp->equipsecondaryIO, player.equipsecondaryIO);
FillIOIdent(asp->equipshieldIO, player.equipshieldIO);
FillIOIdent(asp->leftIO, player.leftIO);
FillIOIdent(asp->rightIO, player.rightIO);
FillIOIdent(asp->curtorch, CURRENT_TORCH);
memcpy(&asp->precast, &Precast, sizeof(PRECAST_STRUCT)*MAX_PRECAST);
//inventaires
for (long iNbBag = 0; iNbBag < 3; iNbBag++)
for (long m = 0; m < INVENTORY_Y; m++)
for (long n = 0; n < INVENTORY_X; n++)
{
FillIOIdent(asp->id_inventory[iNbBag][n][m], inventory[iNbBag][n][m].io);
asp->inventory_show[iNbBag][n][m] = inventory[iNbBag][n][m].show;
}
memcpy(asp->minimap, minimap, sizeof(MINI_MAP_DATA)*MAX_MINIMAPS);
for (long i = 0; i < MAX_MINIMAPS; i++)
asp->minimap[i].tc = 0;
asp->falling = player.falling;
asp->gold = player.gold;
asp->invisibility = inter.iobj[0]->invisibility;
if (player.inzone)
{
ARX_PATH * ap = (ARX_PATH *)asp->inzone;
strcpy(asp->inzone, ap->name);
}
asp->jumpphase = player.jumpphase;
asp->jumpstarttime = player.jumpstarttime;
asp->Last_Movement = player.Last_Movement;
asp->level = player.level;
asp->life = player.life;
asp->mana = player.mana;
asp->maxlife = player.maxlife;
asp->maxmana = player.maxmana;
asp->misc_flags = 0;
if (player.onfirmground)
asp->misc_flags |= 1;
if (WILLRETURNTOCOMBATMODE)
asp->misc_flags |= 2;
memcpy(&asp->physics, &player.physics, sizeof(IO_PHYSICS));
asp->poison = player.poison;
asp->hunger = player.hunger;
asp->sp_flags = 0;
if (sp_arm == 1)
asp->sp_flags |= SP_ARM1;
if (sp_arm == 2)
asp->sp_flags |= SP_ARM2;
if (sp_arm == 3)
asp->sp_flags |= SP_ARM3;
if (sp_max)
asp->sp_flags |= SP_MAX;
if (cur_mr == 3)
asp->sp_flags |= SP_MR;
if (cur_rf == 3)
asp->sp_flags |= SP_RF;
if (sp_wep)
asp->sp_flags |= SP_WEP;
asp->pos.x = player.pos.x;
asp->pos.y = player.pos.y;
asp->pos.z = player.pos.z;
asp->resist_magic = player.resist_magic;
asp->resist_poison = player.resist_poison;
asp->Attribute_Redistribute = player.Attribute_Redistribute;
asp->Skill_Redistribute = player.Skill_Redistribute;
asp->rune_flags = player.rune_flags;
asp->size.x = player.size.x;
asp->size.y = player.size.y;
asp->size.z = player.size.z;
asp->Skill_Stealth = player.Skill_Stealth;
asp->Skill_Mecanism = player.Skill_Mecanism;
asp->Skill_Intuition = player.Skill_Intuition;
asp->Skill_Etheral_Link = player.Skill_Etheral_Link;
asp->Skill_Object_Knowledge = player.Skill_Object_Knowledge;
asp->Skill_Casting = player.Skill_Casting;
asp->Skill_Projectile = player.Skill_Projectile;
asp->Skill_Close_Combat = player.Skill_Close_Combat;
asp->Skill_Defense = player.Skill_Defense;
asp->skin = player.skin;
asp->xp = player.xp;
asp->nb_PlayerQuest = nb_PlayerQuest;
asp->keyring_nb = Keyring_Number;
asp->Global_Magic_Mode = GLOBAL_MAGIC_MODE;
asp->Nb_Mapmarkers = Nb_Mapmarkers;
asp->LAST_VALID_POS.x = LastValidPlayerPos.x;
asp->LAST_VALID_POS.y = LastValidPlayerPos.y;
asp->LAST_VALID_POS.z = LastValidPlayerPos.z;
for (int i = 0; i < MAX_ANIMS; i++)
{
memset(&asp->anims[i], 0, 256);
if (inter.iobj[0]->anims[i] != NULL)
{
strcpy(asp->anims[i], inter.iobj[0]->anims[i]->path + strlen(Project.workingdir));
}
}
for (long k = 0; k < MAX_EQUIPED; k++)
{
if (ValidIONum(player.equiped[k])
&& (player.equiped[k] > 0))
FillIOIdent(asp->equiped[k], inter.iobj[player.equiped[k]]);
else
strcpy(asp->equiped[k], "");
}
for (int i = 0; i < nb_PlayerQuest; i++)
{
memset(dat + pos, 0, 80);
strcpy((char *)(dat + pos), PlayerQuest[i].ident);
pos += 80;
}
for (int i = 0; i < asp->keyring_nb; i++)
{
memcpy((char *)(dat + pos), &Keyring[i], sizeof(KEYRING_SLOT));
pos += sizeof(KEYRING_SLOT);
}
for (int i = 0; i < asp->Nb_Mapmarkers; i++)
{
memcpy((char *)(dat + pos), &Mapmarkers[i], sizeof(ARX_CHANGELEVEL_MAPMARKER_DATA));
pos += sizeof(ARX_CHANGELEVEL_MAPMARKER_DATA);
}
LastValidPlayerPos.x = asp->LAST_VALID_POS.x;
LastValidPlayerPos.y = asp->LAST_VALID_POS.y;
LastValidPlayerPos.z = asp->LAST_VALID_POS.z;
char savefile[256];
sprintf(savefile, "player.sav");
char * compressed = NULL;
long cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
free(dat);
for (int i = 0; i < cpr_pos; i += 2)
compressed[i] = ~compressed[i];
_pSaveBlock->Save(savefile, compressed, cpr_pos);
free(compressed);
for (int i = 1; i < inter.nbmax; i++)
{
if ((IsInPlayerInventory(inter.iobj[i]))
|| (IsPlayerEquipedWith(inter.iobj[i])))
ARX_CHANGELEVEL_Push_IO(inter.iobj[i]);
}
return 1;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Push_AllIO(long num)
{
for (long i = 1; i < inter.nbmax; i++)
{
if ((inter.iobj[i] != NULL)
&& (!(inter.iobj[i]->ioflags & IO_NOSAVE))
&& (!IsInPlayerInventory(inter.iobj[i]))
&& (!IsPlayerEquipedWith(inter.iobj[i]))
)
{
ARX_CHANGELEVEL_Push_IO(inter.iobj[i]);
}
}
return 1;
}
//-----------------------------------------------------------------------------
INTERACTIVE_OBJ * GetObjIOSource(EERIE_3DOBJ * obj)
{
if (!obj)
return NULL;
for (long i = 0; i < inter.nbmax; i++)
{
if ((inter.iobj[i]) && (inter.iobj[i]->obj))
{
if (inter.iobj[i]->obj == obj)
return inter.iobj[i];
}
}
return NULL;
}
// num = num in index file
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Push_IO(INTERACTIVE_OBJ * io)
{
// Check Valid IO
if (!io)
return -1;
// Sets Savefile Name
char savefile[256];
sprintf(savefile, "%s_%04d.sav", GetName(io->filename), io->ident);
// Define Type & Affiliated Structure Size
long type;
long struct_size;
if (io->ioflags & IO_NPC)
{
type = TYPE_NPC;
struct_size = sizeof(ARX_CHANGELEVEL_NPC_IO_SAVE);
}
else if (io->ioflags & IO_ITEM)
{
type = TYPE_ITEM;
struct_size = sizeof(ARX_CHANGELEVEL_ITEM_IO_SAVE);
}
else if (io->ioflags & IO_FIX)
{
type = TYPE_FIX;
struct_size = sizeof(ARX_CHANGELEVEL_FIX_IO_SAVE);
}
else if (io->ioflags & IO_CAMERA)
{
type = TYPE_CAMERA;
struct_size = sizeof(ARX_CHANGELEVEL_CAMERA_IO_SAVE);
}
else
{
type = TYPE_MARKER;
struct_size = sizeof(ARX_CHANGELEVEL_MARKER_IO_SAVE);
}
// Init Changelevel Main IO Save Structure
ARX_CHANGELEVEL_IO_SAVE ais;
memset(&ais, 0, sizeof(ARX_CHANGELEVEL_IO_SAVE));
// Main Buffer
unsigned char * dat = NULL;
long pos = 0;
// Store IO Data in Main IO Save Structure
ais.version = ARX_GAMESAVE_VERSION;
ais.savesystem_type = type;
ais.saveflags = 0;
strcpy(ais.filename, io->filename);
ais.ident = io->ident;
ais.ioflags = io->ioflags;
if ((ais.ioflags & IO_FREEZESCRIPT)
&& ((ARX_SPELLS_GetSpellOn(io, SPELL_PARALYSE) >= 0)
|| (ARX_SPELLS_GetSpellOn(io, SPELL_MASS_PARALYSE) >= 0)))
ais.ioflags &= ~IO_FREEZESCRIPT;
ais.pos.x = io->pos.x;
ais.pos.y = io->pos.y;
ais.pos.z = io->pos.z;
if ((io->obj)
&& (io->obj->pbox)
&& (io->obj->pbox->active))
ais.pos.y -= io->obj->pbox->vert[0].initpos.y;
ais.lastpos.x = io->lastpos.x;
ais.lastpos.y = io->lastpos.y;
ais.lastpos.z = io->lastpos.z;
ais.initpos.x = io->initpos.x;
ais.initpos.y = io->initpos.y;
ais.initpos.z = io->initpos.z;
ais.initangle.x = io->initangle.x;
ais.initangle.y = io->initangle.y;
ais.initangle.z = io->initangle.z;
ais.move.x = io->move.x;
ais.move.y = io->move.y;
ais.move.z = io->move.z;
ais.lastmove.x = io->lastmove.x;
ais.lastmove.y = io->lastmove.y;
ais.lastmove.z = io->lastmove.z;
ais.angle.a = io->angle.a;
ais.angle.b = io->angle.b;
ais.angle.g = io->angle.g;
ais.scale = io->scale;
ais.weight = io->weight;
strcpy(ais.locname, io->locname);
ais.EditorFlags = io->EditorFlags;
ais.GameFlags = io->GameFlags;
if (io == inter.iobj[0])
ais.GameFlags &= ~GFLAG_INVISIBILITY;
ais.material = io->material;
ais.level = io->level;
ais.truelevel = io->truelevel;
ais.scriptload = io->scriptload;
ais.show = io->show;
ais.collision = io->collision;
strcpy(ais.mainevent, io->mainevent);
ais.velocity.x = io->velocity.x;
ais.velocity.y = io->velocity.y;
ais.velocity.z = io->velocity.z;
ais.stopped = io->stopped;
ais.basespeed = io->basespeed;
ais.speed_modif = io->speed_modif;
ais.frameloss = io->frameloss;
ais.rubber = io->rubber;
ais.max_durability = io->max_durability;
ais.durability = io->durability;
ais.poisonous = io->poisonous;
ais.poisonous_count = io->poisonous_count;
ais.head_rot = io->head_rot;
ais.damager_damages = io->damager_damages;
ais.nb_iogroups = io->nb_iogroups;
ais.damager_type = io->damager_type;
ais.type_flags = io->type_flags;
ais.secretvalue = io->secretvalue;
ais.shop_multiply = io->shop_multiply;
ais.aflags = io->aflags;
ais.original_height = io->original_height;
ais.original_radius = io->original_radius;
ais.ignition = io->ignition;
if (io->usepath)
{
ARX_USE_PATH * aup = (ARX_USE_PATH *)io->usepath;
ais.usepath_aupflags = aup->aupflags;
float ulCurTime = aup->_curtime;
ARX_CHECK_ULONG(ulCurTime);
ais.usepath_curtime = ARX_CLEAN_WARN_CAST_ULONG(ulCurTime) ;
Vector_Copy(&ais.usepath_initpos, &aup->initpos);
ais.usepath_lastWP = aup->lastWP;
float ulStartTime = aup->_starttime;
ARX_CHECK_ULONG(ulStartTime);
ais.usepath_starttime = ARX_CLEAN_WARN_CAST_ULONG(ulStartTime);
strcpy(ais.usepath_name, aup->path->name);
}
if (io->shop_category)
strcpy(ais.shop_category, io->shop_category);
else
ais.shop_category[0] = 0;
memset(ais.inventory_skin, 0, 128);
if (io->inventory_skin)
strcpy(ais.inventory_skin, io->inventory_skin);
memset(ais.stepmaterial, 0, 128);
if (io->stepmaterial)
strcpy(ais.stepmaterial, io->stepmaterial);
memset(ais.armormaterial, 0, 128);
if (io->armormaterial)
strcpy(ais.armormaterial, io->armormaterial);
memset(ais.weaponmaterial, 0, 128);
if (io->weaponmaterial)
strcpy(ais.weaponmaterial, io->weaponmaterial);
memset(ais.strikespeech, 0, 128);
if (io->strikespeech)
strcpy(ais.strikespeech, io->strikespeech);
ais.nb_linked = 0;
memset(&ais.linked_data, 0, sizeof(IO_LINKED_DATA)*MAX_LINKED_SAVE);
// Save Animations
for (long i = 0; i < MAX_ANIMS; i++)
{
memset(&ais.anims[i], 0, 256);
if (io->anims[i] != NULL)
{
strcpy(ais.anims[i], io->anims[i]->path + strlen(Project.workingdir));
}
}
// Save Linked Objects
if (io->obj)
{
ais.nb_linked = 0;
for (long n = 0; n < io->obj->nblinked; n++)
{
if (GetObjIOSource((EERIE_3DOBJ *)io->obj->linked[n].obj))
ais.nb_linked++;
}
if (ais.nb_linked > MAX_LINKED_SAVE) ais.nb_linked = MAX_LINKED_SAVE;
long count = 0;
for (int n = 0; n < io->obj->nblinked; n++)
{
if (GetObjIOSource((EERIE_3DOBJ *)io->obj->linked[n].obj))
{
ais.linked_data[count].lgroup = io->obj->linked[count].lgroup;
ais.linked_data[count].lidx = io->obj->linked[count].lidx;
ais.linked_data[count].lidx2 = io->obj->linked[count].lidx2;
memcpy(&ais.linked_data[count].modinfo, &io->obj->linked[count].modinfo, sizeof(EERIE_MOD_INFO));
FillIOIdent(ais.linked_data[count].linked_id, (INTERACTIVE_OBJ *)GetObjIOSource((EERIE_3DOBJ *)io->obj->linked[count].obj));
count++;
}
}
}
if (io->tweakerinfo)
{
ais.system_flags = SYSTEM_FLAG_TWEAKER_INFO;
}
else ais.system_flags = 0;
if (io->inventory)
{
ais.system_flags |= SYSTEM_FLAG_INVENTORY;
}
if (type == TYPE_ITEM)
{
if (io->_itemdata->equipitem)
{
ais.system_flags |= SYSTEM_FLAG_EQUIPITEMDATA;
}
}
if (io->usepath)
ais.system_flags |= SYSTEM_FLAG_USEPATH;
memcpy(&ais.physics, &io->physics, sizeof(IO_PHYSICS));
memcpy(&ais.spellcast_data, &io->spellcast_data, sizeof(IO_SPELLCAST_DATA));
memcpy(&ais.animlayer, &io->animlayer, sizeof(ANIM_USE)*MAX_ANIM_LAYERS);
for (long k = 0; k < MAX_ANIM_LAYERS; k++)
{
ais.animlayer[k].cur_anim = (ANIM_HANDLE *)GetIOAnimIdx2(io, io->animlayer[k].cur_anim);
ais.animlayer[k].next_anim = (ANIM_HANDLE *)GetIOAnimIdx2(io, io->animlayer[k].next_anim);
}
// Save Target Infos
long numtarget = io->targetinfo;
if ((io->ioflags & IO_NPC) && (io->_npcdata->pathfind.listnb > 0) && ValidIONum(io->_npcdata->pathfind.truetarget))
{
numtarget = io->_npcdata->pathfind.truetarget;
}
if (numtarget == -2) strcpy(ais.id_targetinfo, "SELF");
else if (numtarget == -1) strcpy(ais.id_targetinfo, "NONE");
else if (numtarget == 0) strcpy(ais.id_targetinfo, "PLAYER");
else if (ValidIONum(numtarget))
FillIOIdent(ais.id_targetinfo, (INTERACTIVE_OBJ *)inter.iobj[numtarget]);
else strcpy(ais.id_targetinfo, "NONE");
// Save Local Timers ?
long count = 0;
for (int i = 0; i < MAX_TIMER_SCRIPT; i++)
{
if (scr_timer[i].exist)
{
if (scr_timer[i].io == io)
{
count++;
}
}
}
ais.nbtimers = count;
long allocsize =
sizeof(ARX_CHANGELEVEL_IO_SAVE)
+ sizeof(ARX_CHANGELEVEL_SCRIPT_SAVE)
+ io->script.nblvar * (sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE) + 500)
+ sizeof(ARX_CHANGELEVEL_SCRIPT_SAVE)
+ io->over_script.nblvar * (sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE) + 500)
+ struct_size
+ sizeof(IO_TWEAKER_INFO)
+ sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE) + 1024
+ sizeof(IO_GROUP_DATA) * io->nb_iogroups
+ sizeof(TWEAK_INFO) * io->Tweak_nb
+ 48000;
// Allocate Main Save Buffer
dat = (unsigned char *) malloc(allocsize);
if (!dat) HERMES_Memory_Emergency_Out();
memcpy(&ais.halo, &io->halo_native, sizeof(IO_HALO));
ais.Tweak_nb = io->Tweak_nb;
memcpy(dat, &ais, sizeof(ARX_CHANGELEVEL_IO_SAVE));
pos += sizeof(ARX_CHANGELEVEL_IO_SAVE);
long timm = ARXTimeUL(); //treat warning C4244 conversion from 'float' to 'unsigned long''
for (int i = 0; i < MAX_TIMER_SCRIPT; i++)
{
if (scr_timer[i].exist)
{
if (scr_timer[i].io == io)
{
ARX_CHANGELEVEL_TIMERS_SAVE * ats = (ARX_CHANGELEVEL_TIMERS_SAVE *)(dat + pos);
memset(ats, 0, sizeof(ARX_CHANGELEVEL_TIMERS_SAVE));
ats->longinfo = scr_timer[i].longinfo;
ats->msecs = scr_timer[i].msecs;
strcpy(ats->name, scr_timer[i].name);
ats->pos = scr_timer[i].pos;
if (scr_timer[i].es == &io->script)
ats->script = 0;
else ats->script = 1;
ats->tim = (scr_timer[i].tim + scr_timer[i].msecs) - timm;
if (ats->tim < 0) ats->tim = 0;
//else ats->tim=-ats->tim;
ats->times = scr_timer[i].times;
ats->flags = scr_timer[i].flags;
pos += sizeof(ARX_CHANGELEVEL_TIMERS_SAVE);
}
}
}
ARX_CHANGELEVEL_SCRIPT_SAVE * ass = (ARX_CHANGELEVEL_SCRIPT_SAVE *)(dat + pos);
ass->allowevents = io->script.allowevents;
ass->lastcall = io->script.lastcall;
ass->nblvar = io->script.nblvar;
pos += sizeof(ARX_CHANGELEVEL_SCRIPT_SAVE);
long posi = 0;
for (int i = 0; i < io->script.nblvar; i++)
{
ARX_CHANGELEVEL_VARIABLE_SAVE * avs = (ARX_CHANGELEVEL_VARIABLE_SAVE *)(dat + pos);
memset(avs, 0, sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE));
long count;
switch (io->script.lvar[i].type)
{
case TYPE_L_TEXT:
if ((io->script.lvar[i].name[0] == '$') || (io->script.lvar[i].name[0] == '£'))
{
strcpy(avs->name, io->script.lvar[i].name);
if (io->script.lvar[i].text)
count = strlen(io->script.lvar[i].text);
else
count = 0;
avs->fval = (float)(count + 1);
avs->type = TYPE_L_TEXT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
if (avs->fval > 0)
{
ARX_CHECK_SIZET(avs->fval);
memset(dat + pos, 0, ARX_CLEAN_WARN_CAST_SIZET(avs->fval)); //count+1);
if (count > 0)
memcpy(dat + pos, io->script.lvar[i].text, count);
}
pos += (long)avs->fval;
}
else
ass->nblvar--;
break;
case TYPE_L_LONG:
if ((io->script.lvar[i].name[0] == '#') || (io->script.lvar[i].name[0] == '§'))
{
strcpy(avs->name, io->script.lvar[i].name);
avs->fval = (float)io->script.lvar[i].ival;
avs->type = TYPE_L_LONG;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
}
else
ass->nblvar--;
break;
case TYPE_L_FLOAT:
if ((io->script.lvar[i].name[0] == '&') || (io->script.lvar[i].name[0] == '@'))
{
strcpy(avs->name, io->script.lvar[i].name);
avs->fval = io->script.lvar[i].fval;
avs->type = TYPE_L_FLOAT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
}
else
ass->nblvar--;
break;
default:
ass->nblvar--;
break;
}
}
ass = (ARX_CHANGELEVEL_SCRIPT_SAVE *)(dat + pos);
ass->allowevents = io->over_script.allowevents;
ass->lastcall = io->over_script.lastcall;
ass->nblvar = io->over_script.nblvar;
pos += sizeof(ARX_CHANGELEVEL_SCRIPT_SAVE);
posi = 0;
for (int i = 0; i < io->over_script.nblvar; i++)
{
ARX_CHANGELEVEL_VARIABLE_SAVE * avs = (ARX_CHANGELEVEL_VARIABLE_SAVE *)(dat + pos);
memset(avs, 0, sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE));
long count;
switch (io->over_script.lvar[i].type)
{
case TYPE_L_TEXT:
if ((io->script.lvar[i].name[0] == '$') || (io->script.lvar[i].name[0] == '£'))
{
strcpy(avs->name, io->over_script.lvar[i].name);
if (io->over_script.lvar[i].text)
count = strlen(io->over_script.lvar[i].text);
else
count = 0;
avs->fval = (float)(count + 1);
avs->type = TYPE_L_TEXT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
if (avs->fval > 0)
{
ARX_CHECK_SIZET(avs->fval);
memset(dat + pos, 0, ARX_CLEAN_WARN_CAST_SIZET(avs->fval)); //count+1);
if (count > 0)
memcpy(dat + pos, io->over_script.lvar[i].text, count); //+1);
}
pos += (long)avs->fval;
}
else
ass->nblvar--;
break;
case TYPE_L_LONG:
if ((io->script.lvar[i].name[0] == '#') || (io->script.lvar[i].name[0] == '§'))
{
strcpy(avs->name, io->over_script.lvar[i].name);
avs->fval = (float)io->over_script.lvar[i].ival;
avs->type = TYPE_L_LONG;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
}
else
ass->nblvar--;
break;
case TYPE_L_FLOAT:
if ((io->script.lvar[i].name[0] == '&') || (io->script.lvar[i].name[0] == '@'))
{
strcpy(avs->name, io->over_script.lvar[i].name);
avs->fval = io->over_script.lvar[i].fval;
avs->type = TYPE_L_FLOAT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
}
else
ass->nblvar--;
break;
default:
ass->nblvar--;
}
}
long iii;
switch (type)
{
case TYPE_NPC:
ARX_CHANGELEVEL_NPC_IO_SAVE * as;
as = (ARX_CHANGELEVEL_NPC_IO_SAVE *)(dat + pos);
memset(as, 0, sizeof(ARX_CHANGELEVEL_NPC_IO_SAVE));
as->absorb = io->_npcdata->absorb;
as->aimtime = io->_npcdata->aimtime;
as->armor_class = io->_npcdata->armor_class;
as->behavior = io->_npcdata->behavior;
as->behavior_param = io->_npcdata->behavior_param;
as->collid_state = io->_npcdata->collid_state;
as->collid_time = io->_npcdata->collid_time;
as->cut = io->_npcdata->cut;
as->damages = io->_npcdata->damages;
as->detect = io->_npcdata->detect;
as->fightdecision = io->_npcdata->fightdecision;
if (io->_npcdata->life > 0.f)
FillIOIdent(as->id_weapon, (INTERACTIVE_OBJ *)io->_npcdata->weapon);
else
as->id_weapon[0] = 0;
as->lastmouth = io->_npcdata->lastmouth;
as->life = io->_npcdata->life;
as->look_around_inc = io->_npcdata->look_around_inc;
as->mana = io->_npcdata->mana;
as->maxlife = io->_npcdata->maxlife;
as->maxmana = io->_npcdata->maxmana;
as->movemode = io->_npcdata->movemode;
as->moveproblem = io->_npcdata->moveproblem;
as->reachedtarget = io->_npcdata->reachedtarget;
as->speakpitch = io->_npcdata->speakpitch;
as->tactics = io->_npcdata->tactics;
as->tohit = io->_npcdata->tohit;
as->weaponinhand = io->_npcdata->weaponinhand;
strcpy(as->weaponname, io->_npcdata->weaponname);
as->weapontype = io->_npcdata->weapontype;
as->xpvalue = io->_npcdata->xpvalue;
memcpy(as->stacked, io->_npcdata->stacked, sizeof(IO_BEHAVIOR_DATA)*MAX_STACKED_BEHAVIOR);
for (iii = 0; iii < MAX_STACKED_BEHAVIOR; iii++)
{
if ((io->_npcdata->stacked[iii].exist)
&& (ValidIONum(io->_npcdata->stacked[iii].target)
|| io->_npcdata->stacked[iii].target == -2))
{
long trg = io->_npcdata->stacked[iii].target;
if (trg < 0) trg = GetInterNum(io);
if (ValidIONum(trg))
FillIOIdent(as->stackedtarget[iii], (INTERACTIVE_OBJ *)inter.iobj[trg]);
else
strcpy(as->stackedtarget[iii], "NONE");
}
else strcpy(as->stackedtarget[iii], "NONE");
}
as->critical = io->_npcdata->critical;
as->reach = io->_npcdata->reach;
as->backstab_skill = io->_npcdata->backstab_skill;
as->poisonned = io->_npcdata->poisonned;
as->resist_poison = io->_npcdata->resist_poison;
as->resist_magic = io->_npcdata->resist_magic;
as->resist_fire = io->_npcdata->resist_fire;
as->strike_time = io->_npcdata->strike_time;
as->walk_start_time = io->_npcdata->walk_start_time;
as->aiming_start = io->_npcdata->aiming_start;
as->npcflags = io->_npcdata->npcflags;
memset(&as->pathfind, 0, sizeof(IO_PATHFIND));
if (io->_npcdata->pathfind.listnb > 0)
as->pathfind.truetarget = io->_npcdata->pathfind.truetarget;
else as->pathfind.truetarget = -1;
if (io->_npcdata->ex_rotate)
{
ais.saveflags |= SAVEFLAGS_EXTRA_ROTATE;
memcpy(&as->ex_rotate, io->_npcdata->ex_rotate, sizeof(EERIE_EXTRA_ROTATE));
}
as->blood_color = io->_npcdata->blood_color;
as->fDetect = io->_npcdata->fDetect;
as->cuts = io->_npcdata->cuts;
pos += struct_size;
break;
case TYPE_ITEM:
ARX_CHANGELEVEL_ITEM_IO_SAVE * ai;
ai = (ARX_CHANGELEVEL_ITEM_IO_SAVE *)(dat + pos);
memset(ai, 0, sizeof(ARX_CHANGELEVEL_ITEM_IO_SAVE));
ai->price = io->_itemdata->price;
ai->count = io->_itemdata->count;
ai->maxcount = io->_itemdata->maxcount;
ai->food_value = io->_itemdata->food_value;
ai->stealvalue = io->_itemdata->stealvalue;
ai->playerstacksize = io->_itemdata->playerstacksize;
ai->LightValue = io->_itemdata->LightValue;
if (io->_itemdata->equipitem)
{
memcpy(&ai->equipitem, io->_itemdata->equipitem, sizeof(IO_EQUIPITEM));
}
pos += struct_size;
break;
case TYPE_FIX:
ARX_CHANGELEVEL_FIX_IO_SAVE * af;
af = (ARX_CHANGELEVEL_FIX_IO_SAVE *)(dat + pos);
memset(af, 0, sizeof(ARX_CHANGELEVEL_FIX_IO_SAVE));
af->trapvalue = io->_fixdata->trapvalue;
pos += struct_size;
break;
case TYPE_CAMERA:
ARX_CHANGELEVEL_CAMERA_IO_SAVE * ac;
ac = (ARX_CHANGELEVEL_CAMERA_IO_SAVE *)(dat + pos);
memset(ac, 0, sizeof(ARX_CHANGELEVEL_CAMERA_IO_SAVE));
memcpy(&ac->cam, io->_camdata, sizeof(EERIE_CAMERA));
pos += struct_size;
break;
case TYPE_MARKER:
ARX_CHANGELEVEL_MARKER_IO_SAVE * am;
am = (ARX_CHANGELEVEL_MARKER_IO_SAVE *)(dat + pos);
memset(am, 0, sizeof(ARX_CHANGELEVEL_MARKER_IO_SAVE));
am->dummy = 0;
pos += struct_size;
break;
}
if (ais.system_flags & SYSTEM_FLAG_INVENTORY)
{
ARX_CHANGELEVEL_INVENTORY_DATA_SAVE * aids;
aids = (ARX_CHANGELEVEL_INVENTORY_DATA_SAVE *)(dat + pos);
memset(aids, 0, sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE));
long m, n;
INVENTORY_DATA * inv = (INVENTORY_DATA *)io->inventory;
FillIOIdent(aids->io, (INTERACTIVE_OBJ *)inv->io);
aids->sizex = inv->sizex;
aids->sizey = inv->sizey;
for (m = 0; m < aids->sizex; m++)
for (n = 0; n < aids->sizey; n++)
{
aids->initio[m][n][0] = 0;
if (inv->slot[m][n].io)
FillIOIdent(aids->slot_io[m][n], inv->slot[m][n].io);
else
aids->slot_io[m][n][0] = 0;
aids->slot_show[m][n] = inv->slot[m][n].show;
}
pos += sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE);
}
if (io->tweakerinfo)
{
memcpy(dat + pos, io->tweakerinfo, sizeof(IO_TWEAKER_INFO));
pos += sizeof(IO_TWEAKER_INFO);
}
for (long ii = 0; ii < io->nb_iogroups; ii++)
{
IO_GROUP_DATA * igd = (IO_GROUP_DATA *)(dat + pos);
pos += sizeof(IO_GROUP_DATA);
memcpy(igd, &io->iogroups[ii], sizeof(IO_GROUP_DATA));
}
for (int ii = 0; ii < io->Tweak_nb; ii++)
{
TWEAK_INFO * ti = (TWEAK_INFO *)(dat + pos);
pos += sizeof(TWEAK_INFO);
memcpy(ti, &io->Tweaks[ii], sizeof(TWEAK_INFO));
}
if ((pos > allocsize) && (!FOR_EXTERNAL_PEOPLE))
{
char tex[256];
sprintf(tex, "SaveBuffer Overflow %d >> %d", pos, allocsize);
ShowPopup(tex);
}
char * compressed = NULL;
long cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
free(dat);
for (int i = 0; i < cpr_pos; i += 2)
compressed[i] = ~compressed[i];
_pSaveBlock->Save(savefile, compressed, cpr_pos);
free(compressed);
return 1;
}
//-----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//// LOADING ////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_Index(ARX_CHANGELEVEL_INDEX * asi, long num)
{
unsigned char * dat;
long pos = 0;
char loadfile[256];
char _error[256];
sprintf(loadfile, "lvl%03d.sav", num);
long size;
size = _pSaveBlock->GetSize(loadfile);
if (size <= 0)
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
ShowPopup(_error);
return -1;
}
char * compressed = (char *) GetStdBuffer(size);
if (!compressed) HERMES_Memory_Emergency_Out();
if (!_pSaveBlock->Read(loadfile, (char *)compressed))
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
ShowPopup(_error);
return -1;
}
for (long i = 0; i < size; i += 2)
compressed[i] = ~compressed[i];
long ssize = size;
dat = (unsigned char *)STD_Explode(compressed, ssize, &size);
memcpy(asi, dat, sizeof(ARX_CHANGELEVEL_INDEX));
pos += sizeof(ARX_CHANGELEVEL_INDEX);
if (asi->nb_inter)
{
idx_io = (ARX_CHANGELEVEL_IO_INDEX *) malloc(sizeof(ARX_CHANGELEVEL_IO_INDEX) * asi->nb_inter);
if (!idx_io) HERMES_Memory_Emergency_Out();
memcpy(idx_io, dat + pos, sizeof(ARX_CHANGELEVEL_IO_INDEX)*asi->nb_inter);
pos += sizeof(ARX_CHANGELEVEL_IO_INDEX) * asi->nb_inter;
}
else idx_io = NULL;
// Skip Path info (used later !)
pos += sizeof(ARX_CHANGELEVEL_PATH) * asi->nb_paths;
// Restore Ambiances
if (asi->ambiances_data_size)
{
void * playlist = (void *)(dat + pos);
pos += asi->ambiances_data_size;
ARX_SOUND_AmbianceRestorePlayList(playlist, asi->ambiances_data_size);
}
free(dat);
return 1;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_Zones_n_Lights(ARX_CHANGELEVEL_INDEX * asi, long num)
{
unsigned char * dat;
long pos = 0;
char loadfile[256];
char _error[256];
long size;
sprintf(loadfile, "lvl%03d.sav", num);
size = _pSaveBlock->GetSize(loadfile);
if (size < 0)
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
ShowPopup(_error);
return -1;
}
char * compressed = (char *) GetStdBuffer(size);
if (!compressed) HERMES_Memory_Emergency_Out();
if (!_pSaveBlock->Read(loadfile, (char *)compressed))
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
ShowPopup(_error);
return -1;
}
for (long i = 0; i < size; i += 2)
compressed[i] = ~compressed[i];
long ssize = size;
dat = (unsigned char *)STD_Explode(compressed, ssize, &size); //pos,&cpr_pos);
// Skip Changelevel Index
pos += sizeof(ARX_CHANGELEVEL_INDEX);
// Skip Inter idx
pos += sizeof(ARX_CHANGELEVEL_IO_INDEX) * asi->nb_inter;
// Now Restore Paths
ARX_CHANGELEVEL_PATH * acp;
for (int i = 0; i < asi->nb_paths; i++)
{
acp = (ARX_CHANGELEVEL_PATH *)(dat + pos);
ARX_PATH * ap = ARX_PATH_GetAddressByName(acp->name);
if (ap)
{
if (acp->controled[0] == 0)
ap->controled[0] = 0;
else
{
strcpy(ap->controled, acp->controled);
}
}
pos += sizeof(ARX_CHANGELEVEL_PATH);
}
if (asi->ambiances_data_size > 0)
{
pos += asi->ambiances_data_size;
}
for (int i = 0; i < asi->nb_lights; i++)
{
ARX_CHANGELEVEL_LIGHT * acl = (ARX_CHANGELEVEL_LIGHT *)(dat + pos);
pos += sizeof(ARX_CHANGELEVEL_LIGHT);
long count = 0;
for (long j = 0; j < MAX_LIGHTS; j++)
{
EERIE_LIGHT * el = GLight[j];
if ((el != NULL) && (!(el->type & TYP_SPECIAL1)))
{
if (count == i)
{
el->status = acl->status;
j = MAX_LIGHTS + 1;
}
count++;
}
}
}
free(dat);
return 1;
}
extern long NO_GMOD_RESET;
extern long FOR_EXTERNAL_PEOPLE;
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_Level(ARX_CHANGELEVEL_INDEX * asi, long num, long FirstTime)
{
char tex[256];
char postxt[256];
char lev[256];
char ftemp[256];
strcpy(postxt, "NONE");
GetLevelNameByNum(num, lev);
if (!FirstTime)
{
DONT_LOAD_INTERS = 1;
}
else
{
DONT_LOAD_INTERS = 0;
}
LOAD_N_DONT_ERASE = 1;
sprintf(tex, "LEVEL%s", lev);
sprintf(ftemp, "%sGraph\\Levels\\%s\\%s.DLF", Project.workingdir, tex, tex);
if (!PAK_FileExist(ftemp))
{
sprintf(tex, "Unable To Find %s", ftemp);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(tex);
return 0;
}
LoadLevelScreen(GDevice, num);
SetEditMode(1, false);
if (ARX_CHANGELEVEL_Pop_Globals() != 1)
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load Globals data");
}
DanaeLoadLevel(GDevice, ftemp);
CleanScriptLoadedIO();
FirstFrame = 1;
DONT_LOAD_INTERS = 0;
if (FirstTime)
{
RestoreInitialIOStatus();
for (long i = 1; i < inter.nbmax; i++)
{
if (inter.iobj[i] != NULL)
{
if (!inter.iobj[i]->scriptload)
ARX_SCRIPT_Reset(inter.iobj[i], 1);
}
}
EDITMODE = 0;
BLOCK_PLAYER_CONTROLS = 0;
ARX_INTERFACE_Reset();
EERIE_ANIMMANAGER_PurgeUnused();
}
else
{
EDITMODE = 0;
BLOCK_PLAYER_CONTROLS = 0;
ARX_INTERFACE_Reset();
EERIE_ANIMMANAGER_PurgeUnused();
}
memcpy(&stacked, &asi->gmods_stacked, sizeof(GLOBAL_MODS));
memcpy(&desired, &asi->gmods_desired, sizeof(GLOBAL_MODS));
memcpy(¤t, &asi->gmods_current, sizeof(GLOBAL_MODS));
NO_GMOD_RESET = 1;
ARX_TIME_Force_Time_Restore(ARX_CHANGELEVEL_DesiredTime);//asi.time);
FORCE_TIME_RESTORE = ARX_CHANGELEVEL_DesiredTime;
return 1;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_Player(ARX_CHANGELEVEL_INDEX * asi, ARX_CHANGELEVEL_PLAYER * asp)
{
char loadfile[256];
char _error[256];
sprintf(loadfile, "player.sav");
long size = _pSaveBlock->GetSize(loadfile);
if (size <= 0)
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
ShowPopup(_error);
return -1;
}
char * compressed = (char *) GetStdBuffer(size);
if (!compressed) HERMES_Memory_Emergency_Out();
_pSaveBlock->Read(loadfile, (char *)compressed);
for (long i = 0; i < size; i += 2)
compressed[i] = ~compressed[i];
long ssize = size;
char * dat = (char *)STD_Explode(compressed, ssize, &size);
memcpy(asp, dat, sizeof(ARX_CHANGELEVEL_PLAYER));
//free(compressed);
player.AimTime = asp->AimTime;
player.desiredangle.a = player.angle.a = asp->angle.a;
player.desiredangle.b = player.angle.b = asp->angle.b;
player.angle.g = asp->angle.g;
ARX_CHECK_UCHAR(asp->armor_class);
player.armor_class = ARX_CLEAN_WARN_CAST_UCHAR(asp->armor_class);
player.Attribute_Constitution = asp->Attribute_Constitution;
player.Attribute_Dexterity = asp->Attribute_Dexterity;
player.Attribute_Mind = asp->Attribute_Mind;
player.Attribute_Strength = asp->Attribute_Strength;
player.Critical_Hit = asp->Critical_Hit;
player.Current_Movement = asp->Current_Movement;
player.damages = asp->damages;
player.doingmagic = asp->doingmagic;
player.playerflags = asp->playerflags;
if (asp->TELEPORT_TO_LEVEL[0]) strcpy(TELEPORT_TO_LEVEL, asp->TELEPORT_TO_LEVEL);
else memset(TELEPORT_TO_LEVEL, 0, 64);
if (asp->TELEPORT_TO_POSITION[0]) strcpy(TELEPORT_TO_POSITION, asp->TELEPORT_TO_POSITION);
else memset(TELEPORT_TO_POSITION, 0, 64);
TELEPORT_TO_ANGLE = asp->TELEPORT_TO_ANGLE;
CHANGE_LEVEL_ICON = asp->CHANGE_LEVEL_ICON;
player.bag = asp->bag;
memcpy(&Precast, &asp->precast, sizeof(PRECAST_STRUCT)*MAX_PRECAST);
player.Interface = asp->Interface;
player.Interface &= ~INTER_MAP;
player.falling = asp->falling;
player.gold = asp->gold;
inter.iobj[0]->invisibility = asp->invisibility;
ARX_PATH * ap = ARX_PATH_GetAddressByName(asp->inzone);
player.inzone = ap;
player.jumpphase = asp->jumpphase;
player.jumpstarttime = asp->jumpstarttime;
player.Last_Movement = asp->Last_Movement;
ARX_CHECK_UCHAR(asp->level);
player.level = ARX_CLEAN_WARN_CAST_UCHAR(asp->level);
player.life = asp->life;
player.mana = asp->mana;
player.maxlife = asp->maxlife;
player.maxmana = asp->maxmana;
if (asp->misc_flags & 1)
player.onfirmground = 1;
else
player.onfirmground = 0;
if (asp->misc_flags & 2)
WILLRETURNTOCOMBATMODE = 1;
else
WILLRETURNTOCOMBATMODE = 0;
memcpy(&player.physics, &asp->physics, sizeof(IO_PHYSICS));
player.poison = asp->poison;
player.hunger = asp->hunger;
player.pos.x = asp->pos.x;
player.pos.y = asp->pos.y;
player.pos.z = asp->pos.z;
if (asp->sp_flags & SP_ARM1)
sp_arm = 1;
else if (asp->sp_flags & SP_ARM2)
sp_arm = 2;
else if (asp->sp_flags & SP_ARM3)
sp_arm = 3;
else
sp_arm = 0;
if (asp->sp_flags & SP_MAX)
{
cur_mx = 3;
sp_max = 1;
}
else
{
cur_mx = 0;
sp_max = 0;
}
if (asp->sp_flags & SP_MR)
{
cur_mr = 3;
}
else
{
cur_mr = 0;
}
if (asp->sp_flags & SP_RF)
cur_rf = 3;
else
cur_rf = 0;
if (asp->sp_flags & SP_WEP)
{
cur_pom = 3;
sp_wep = 1;
}
else
{
cur_pom = 0;
sp_wep = 0;
}
if (inter.iobj[0])
{
Vector_Copy(&inter.iobj[0]->pos, &player.pos);
inter.iobj[0]->pos.y += 170.f;
}
Vector_Copy(&WILL_RESTORE_PLAYER_POSITION, &asp->pos);
WILL_RESTORE_PLAYER_POSITION_FLAG = 1;
ARX_CHECK_UCHAR(asp->resist_magic);
ARX_CHECK_UCHAR(asp->resist_poison);
player.resist_magic = ARX_CLEAN_WARN_CAST_UCHAR(asp->resist_magic);
player.resist_poison = ARX_CLEAN_WARN_CAST_UCHAR(asp->resist_poison);
ARX_CHECK_UCHAR(asp->Attribute_Redistribute);
ARX_CHECK_UCHAR(asp->Skill_Redistribute);
player.Attribute_Redistribute = ARX_CLEAN_WARN_CAST_UCHAR(asp->Attribute_Redistribute);
player.Skill_Redistribute = ARX_CLEAN_WARN_CAST_UCHAR(asp->Skill_Redistribute);
player.rune_flags = asp->rune_flags;
player.size.x = asp->size.x;
player.size.y = asp->size.y;
player.size.z = asp->size.z;
player.Skill_Stealth = asp->Skill_Stealth;
player.Skill_Mecanism = asp->Skill_Mecanism;
player.Skill_Intuition = asp->Skill_Intuition;
player.Skill_Etheral_Link = asp->Skill_Etheral_Link;
player.Skill_Object_Knowledge = asp->Skill_Object_Knowledge;
player.Skill_Casting = asp->Skill_Casting;
player.Skill_Projectile = asp->Skill_Projectile;
player.Skill_Close_Combat = asp->Skill_Close_Combat;
player.Skill_Defense = asp->Skill_Defense;
ARX_CHECK_CHAR(asp->skin);
player.skin = ARX_CLEAN_WARN_CAST_CHAR(asp->skin);
player.xp = asp->xp;
GLOBAL_MAGIC_MODE = asp->Global_Magic_Mode;
ARX_MINIMAP_PurgeTC();
memcpy(minimap, asp->minimap, sizeof(MINI_MAP_DATA)*MAX_MINIMAPS);
INTERACTIVE_OBJ * io = inter.iobj[0];
for (int i = 0; i < MAX_ANIMS; i++)
{
if (io->anims[i] != NULL)
{
ReleaseAnimFromIO(io, i);
}
if (asp->anims[i][0])
{
char tex[256];
sprintf(tex, "%s%s", Project.workingdir, asp->anims[i]);
io->anims[i] = EERIE_ANIMMANAGER_Load(tex);
}
}
for (int iNbBag = 0; iNbBag < 3; iNbBag++)
{
for (long m = 0; m < INVENTORY_Y; m++)
for (long n = 0; n < INVENTORY_X; n++)
{
inventory[iNbBag][n][m].io = ConvertToValidIO(asp->id_inventory[iNbBag][n][m]);
}
}
ARX_PLAYER_Quest_Init();
long pos = sizeof(ARX_CHANGELEVEL_PLAYER);
for (int i = 0; i < asp->nb_PlayerQuest; i++)
{
ARX_PLAYER_Quest_Add((char *)(dat + pos), true);
pos += 80;
}
ARX_KEYRING_Init();
for (int i = 0; i < asp->keyring_nb; i++)
{
char * key = (char *)(dat + pos);
pos += sizeof(KEYRING_SLOT);
ARX_KEYRING_Add(key);
}
ARX_MAPMARKER_Init();
for (int i = 0; i < asp->Nb_Mapmarkers; i++)
{
ARX_CHANGELEVEL_MAPMARKER_DATA * acmd = (ARX_CHANGELEVEL_MAPMARKER_DATA *)(dat + pos);
ARX_MAPMARKER_Add(acmd->x, acmd->y, acmd->lvl, acmd->string);
memcpy((char *)(dat + pos), &Mapmarkers[i], sizeof(ARX_CHANGELEVEL_MAPMARKER_DATA));
pos += sizeof(ARX_CHANGELEVEL_MAPMARKER_DATA);
}
ARX_PLAYER_Restore_Skin();
ARX_PLAYER_Modify_XP(0);
return 1;
}
//-----------------------------------------------------------------------------
void ReleaseTio()
{
if (tio)
{
free(tio);
tio = NULL;
}
nb_tio = 0;
}
extern long ARX_NPC_ApplyCuts(INTERACTIVE_OBJ * io);
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_IO(char * ident)
{
if (!stricmp(ident, "NONE")) return -1;
char loadfile[256];
ARX_CHANGELEVEL_IO_SAVE * ais;
unsigned char * dat;
long pos = 0;
long size = 0;
sprintf(loadfile, "%s.sav", ident);
long t = GetTargetByNameTarget(ident);
if (ValidIONum(t))
return t;
if (NEED_LOG)
{
char temp[256];
sprintf(temp, "--> Before ARX_CHANGELEVEL_Pop_IO(%s)", ident);
LogData(temp);
}
size = _pSaveBlock->GetSize(loadfile);
if (size < 0)
{
char _error[256];
sprintf(_error, "Unable to Open %s for Read...", loadfile);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(_error);
return -1;
}
char * compressed = (char *)GetStdBuffer(size);
if (!compressed) HERMES_Memory_Emergency_Out();
if (!_pSaveBlock->Read(loadfile, (char *)compressed))
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Unable to Read Data");
return -1;
}
for (long i = 0; i < size; i += 2)
compressed[i] = ~compressed[i];
long ssize = size;
dat = (unsigned char *)STD_Explode(compressed, ssize, &size);
// Ignore object if can't explode file
if (!dat)
{
char tcText[256];
sprintf(tcText, "%s", ident, 0);
MessageBox(NULL, tcText, "Error while loading...", 0);
return -1;
}
ais = (ARX_CHANGELEVEL_IO_SAVE *)dat;
if (ais->version != ARX_GAMESAVE_VERSION)
{
free(dat);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Invalid PopIO version");
return -1;
}
pos += sizeof(ARX_CHANGELEVEL_IO_SAVE);
if ((ais->show == SHOW_FLAG_DESTROYED)
|| (ais->ioflags & IO_NOSAVE))
{
free(dat);
return -1;
}
if (NEED_LOG)
{
char temp[256];
sprintf(temp, "--> Phase2 ARX_CHANGELEVEL_Pop_IO(%s)", ident);
LogData(temp);
}
DANAE_LS_INTER dli;
dli.angle.a = ais->angle.a;
dli.angle.b = ais->angle.b;
dli.angle.g = ais->angle.g;
long num = atoi(ident + strlen(ident) - 4);
dli.ident = num;
strcpy(dli.name, ais->filename);
dli.pos.x = ais->pos.x;
dli.pos.y = ais->pos.y;
dli.pos.z = ais->pos.z;
INTERACTIVE_OBJ * tmp = LoadInter_Ex(&dli, &MSP);
long idx = -1;
INTERACTIVE_OBJ * io = NULL;
if (tmp)
{
io = tmp;
idx = GetInterNum(io);
long Gaids_Number = idx;
_Gaids[Gaids_Number] = (ARX_CHANGELEVEL_INVENTORY_DATA_SAVE *) malloc(sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE));
if (!_Gaids[Gaids_Number]) HERMES_Memory_Emergency_Out();
memset(_Gaids[Gaids_Number], 0, sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE));
io->room_flags = 1;
io->room = -1;
io->no_collide = -1;
io->ioflags = ais->ioflags;
io->ioflags &= ~IO_FREEZESCRIPT;
io->pos.x = ais->pos.x;
io->pos.y = ais->pos.y;
io->pos.z = ais->pos.z;
io->lastpos.x = ais->lastpos.x;
io->lastpos.y = ais->lastpos.y;
io->lastpos.z = ais->lastpos.z;
io->move.x = ais->move.x;
io->move.y = ais->move.y;
io->move.z = ais->move.z;
io->lastmove.x = ais->lastmove.x;
io->lastmove.y = ais->lastmove.y;
io->lastmove.z = ais->lastmove.z;
io->initpos.x = ais->initpos.x;
io->initpos.y = ais->initpos.y;
io->initpos.z = ais->initpos.z;
io->initangle.x = ais->initangle.x;
io->initangle.y = ais->initangle.y;
io->initangle.z = ais->initangle.z;
io->angle.a = ais->angle.a;
io->angle.b = ais->angle.b;
io->angle.g = ais->angle.g;
io->scale = ais->scale;
io->weight = ais->weight;
strcpy(io->locname, ais->locname);
io->EditorFlags = ais->EditorFlags;
io->GameFlags = ais->GameFlags;
io->material = ais->material;
io->level = ais->level;
io->truelevel = ais->truelevel;
// Script data
io->scriptload = ais->scriptload;
io->show = ais->show;
io->collision = ais->collision;
strcpy(io->mainevent, ais->mainevent);
// Physics data
io->velocity.x = ais->velocity.x;
io->velocity.y = ais->velocity.y;
io->velocity.z = ais->velocity.z;
io->stopped = ais->stopped;
io->basespeed = 1;
io->speed_modif = 0.f;
io->frameloss = 0;
io->rubber = ais->rubber;
io->max_durability = ais->max_durability;
io->durability = ais->durability;
io->poisonous = ais->poisonous;
io->poisonous_count = ais->poisonous_count;
io->head_rot = ais->head_rot;
io->damager_damages = ais->damager_damages;
io->nb_iogroups = ais->nb_iogroups;
io->damager_type = ais->damager_type;
io->type_flags = ais->type_flags;
io->secretvalue = ais->secretvalue;
io->shop_multiply = ais->shop_multiply;
io->aflags = ais->aflags;
io->original_height = ais->original_height;
io->original_radius = ais->original_radius;
io->ignition = ais->ignition;
if (ais->system_flags & SYSTEM_FLAG_USEPATH)
{
io->usepath = (void *)malloc(sizeof(ARX_USE_PATH));
ARX_USE_PATH * aup = (ARX_USE_PATH *)io->usepath;
aup->aupflags = ais->usepath_aupflags;
aup->_curtime = ARX_CLEAN_WARN_CAST_FLOAT(ais->usepath_curtime);
Vector_Copy(&aup->initpos, &ais->usepath_initpos);
aup->lastWP = ais->usepath_lastWP;
aup->_starttime = ARX_CLEAN_WARN_CAST_FLOAT(ais->usepath_starttime);
ARX_PATH * ap = ARX_PATH_GetAddressByName(ais->usepath_name);
aup->path = ap;
}
if (ais->shop_category[0])
io->shop_category = strdup(ais->shop_category);
else
io->shop_category = NULL;
memcpy(&io->halo_native, &ais->halo, sizeof(IO_HALO));
io->halo_native.dynlight = -1;
io->halo.dynlight = -1;
ARX_HALO_SetToNative(io);
if (ais->inventory_skin[0])
{
io->inventory_skin = (char *) malloc(strlen(ais->inventory_skin) + 1);
if (!io->inventory_skin) HERMES_Memory_Emergency_Out();
strcpy(io->inventory_skin, ais->inventory_skin);
}
else io->stepmaterial = NULL;
if (ais->stepmaterial[0])
{
io->stepmaterial = (char *) malloc(strlen(ais->stepmaterial) + 1);
if (!io->stepmaterial) HERMES_Memory_Emergency_Out();
strcpy(io->stepmaterial, ais->stepmaterial);
}
else io->stepmaterial = NULL;
if (ais->armormaterial[0])
{
io->armormaterial = (char *) malloc(strlen(ais->armormaterial) + 1);
if (!io->armormaterial) HERMES_Memory_Emergency_Out();
strcpy(io->armormaterial, ais->armormaterial);
}
else io->armormaterial = NULL;
if (ais->weaponmaterial[0])
{
io->weaponmaterial = (char *) malloc(strlen(ais->weaponmaterial) + 1);
if (!io->weaponmaterial) HERMES_Memory_Emergency_Out();
strcpy(io->weaponmaterial, ais->weaponmaterial);
}
else io->weaponmaterial = NULL;
if (ais->strikespeech[0])
{
io->strikespeech = (char *) malloc(strlen(ais->strikespeech) + 1);
if (!io->strikespeech) HERMES_Memory_Emergency_Out();
strcpy(io->strikespeech, ais->strikespeech);
}
else io->strikespeech = NULL;
for (long i = 0; i < MAX_ANIMS; i++)
{
if (io->anims[i] != NULL)
{
ReleaseAnimFromIO(io, i);
}
if (ais->anims[i][0])
{
char tex[256];
if ((strlen(Project.workingdir) + strlen(ais->anims[i])) > 256)
{
continue;
}
sprintf(tex, "%s%s", Project.workingdir, ais->anims[i]);
io->anims[i] = EERIE_ANIMMANAGER_Load(tex);
if (io->anims[i] == NULL)
{
if (io->ioflags & IO_NPC)
sprintf(tex, "%sGRAPH\\OBJ3D\\ANIMS\\NPC\\%s%s", Project.workingdir, GetName(ais->anims[i]), GetExt(ais->anims[i]));
else
sprintf(tex, "%sGRAPH\\OBJ3D\\ANIMS\\FIX_Inter\\%s%s", Project.workingdir, GetName(ais->anims[i]), GetExt(ais->anims[i]));
io->anims[i] = EERIE_ANIMMANAGER_Load(tex);
}
}
}
memcpy(&io->spellcast_data, &ais->spellcast_data, sizeof(IO_SPELLCAST_DATA));
memcpy(&io->physics, &ais->physics, sizeof(IO_PHYSICS));
memcpy(&io->animlayer, &ais->animlayer, sizeof(ANIM_USE)*MAX_ANIM_LAYERS);
for (long k = 0; k < MAX_ANIM_LAYERS; k++)
{
long nn = (long)ais->animlayer[k].cur_anim;
if (nn == -1) io->animlayer[k].cur_anim = NULL;
else io->animlayer[k].cur_anim = (ANIM_HANDLE *)io->anims[nn];
nn = (long)ais->animlayer[k].next_anim;
if (nn == -1) io->animlayer[k].next_anim = NULL;
else io->animlayer[k].next_anim = (ANIM_HANDLE *)io->anims[nn];
}
// Target Info
strcpy(_Gaids[Gaids_Number]->targetinfo, ais->id_targetinfo);
ARX_SCRIPT_Timer_Clear_By_IO(io);
for (int i = 0; i < ais->nbtimers; i++)
{
ARX_CHANGELEVEL_TIMERS_SAVE * ats = (ARX_CHANGELEVEL_TIMERS_SAVE *)(dat + pos);
ARX_CHECK_SHORT(ats->flags);
short sFlags = ARX_CLEAN_WARN_CAST_SHORT(ats->flags);
long num = ARX_SCRIPT_Timer_GetFree();
if (num != -1)
{
ActiveTimers++;
if (ats->script)
scr_timer[num].es = &io->over_script;
else
scr_timer[num].es = &io->script;
scr_timer[num].flags = sFlags;
scr_timer[num].exist = 1;
scr_timer[num].io = io;
scr_timer[num].msecs = ats->msecs;
scr_timer[num].namelength = strlen(ats->name) + 1;
scr_timer[num].name = (char *) malloc(scr_timer[num].namelength);
if (!scr_timer[num].name) HERMES_Memory_Emergency_Out();
strcpy(scr_timer[num].name, ats->name);
scr_timer[num].pos = ats->pos;
float tt = ARX_CHANGELEVEL_DesiredTime + ats->tim;
if (tt < 0) scr_timer[num].tim = 0; //;
else
{
ARX_CHECK_ULONG(tt);
scr_timer[num].tim = ARX_CLEAN_WARN_CAST_ULONG(tt) ;
}
scr_timer[num].times = ats->times;
}
pos += sizeof(ARX_CHANGELEVEL_TIMERS_SAVE);
}
//////////////////
ARX_CHANGELEVEL_SCRIPT_SAVE * ass = (ARX_CHANGELEVEL_SCRIPT_SAVE *)(dat + pos);
io->script.allowevents = ass->allowevents;
io->script.nblvar = 0;
if (io->script.lvar)
{
free(io->script.lvar);
io->script.lvar = NULL;
}
if (ass->nblvar > 0)
{
io->script.lvar = (SCRIPT_VAR *) malloc(sizeof(SCRIPT_VAR) * ass->nblvar);
if (!io->script.lvar) HERMES_Memory_Emergency_Out();
}
else io->script.lvar = NULL;
io->script.nblvar = ass->nblvar;
long ERRCOUNT = 0;
pos += sizeof(ARX_CHANGELEVEL_SCRIPT_SAVE);
for (int i = 0; i < ass->nblvar; i++)
{
ARX_CHANGELEVEL_VARIABLE_SAVE * avs = (ARX_CHANGELEVEL_VARIABLE_SAVE *)(dat + pos);
memset(&io->script.lvar[i], 0, sizeof(SCRIPT_VAR));
retry:
;
switch (avs->type)
{
case TYPE_L_TEXT:
strcpy(io->script.lvar[i].name, avs->name);
io->script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->script.lvar[i].ival);
io->script.lvar[i].type = TYPE_L_TEXT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
if (io->script.lvar[i].ival)
{
io->script.lvar[i].text = (char *) malloc(io->script.lvar[i].ival + 1);
if (!io->script.lvar[i].text) HERMES_Memory_Emergency_Out();
memset(io->script.lvar[i].text, 0, io->script.lvar[i].ival + 1);
memcpy(io->script.lvar[i].text, dat + pos, io->script.lvar[i].ival);
pos += io->script.lvar[i].ival;
io->script.lvar[i].ival = strlen(io->script.lvar[i].text) + 1;
if (io->script.lvar[i].text[0] == 'Ì')
io->script.lvar[i].text[0] = 0;
}
else
{
io->script.lvar[i].text = NULL;
io->script.lvar[i].ival = 0;
}
break;
case TYPE_L_LONG:
strcpy(io->script.lvar[i].name, avs->name);
io->script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->script.lvar[i].ival);
io->script.lvar[i].type = TYPE_L_LONG;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
case TYPE_L_FLOAT:
strcpy(io->script.lvar[i].name, avs->name);
io->script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->script.lvar[i].ival);
io->script.lvar[i].type = TYPE_L_FLOAT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
default:
if ((avs->name[0] == '$') || (avs->name[0] == '£'))
{
avs->type = TYPE_L_TEXT;
goto retry;
}
if ((avs->name[0] == '#') || (avs->name[0] == '§'))
{
avs->type = TYPE_L_LONG;
goto retry;
}
if ((avs->name[0] == '&') || (avs->name[0] == '@'))
{
avs->type = TYPE_L_FLOAT;
goto retry;
}
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
strcpy(io->script.lvar[i].name, avs->name);
io->script.lvar[i].fval = 0;
io->script.lvar[i].ival = 0;
io->script.lvar[i].type = TYPE_L_LONG;
ERRCOUNT++;
ass->nblvar = i;
goto corrupted;
break;
}
}
ass = (ARX_CHANGELEVEL_SCRIPT_SAVE *)(dat + pos);
io->over_script.allowevents = ass->allowevents;
io->over_script.nblvar = 0;
if (io->over_script.lvar)
{
free(io->over_script.lvar);
io->over_script.lvar = NULL;
}
if (ass->nblvar)
{
io->over_script.lvar = (SCRIPT_VAR *) malloc(sizeof(SCRIPT_VAR) * ass->nblvar);
if (!io->over_script.lvar) HERMES_Memory_Emergency_Out();
}
//"Script Var"
else io->over_script.lvar = NULL;
io->over_script.nblvar = ass->nblvar;
pos += sizeof(ARX_SCRIPT_SAVE);
for (int i = 0; i < ass->nblvar; i++)
{
ARX_CHANGELEVEL_VARIABLE_SAVE * avs = (ARX_CHANGELEVEL_VARIABLE_SAVE *)(dat + pos);
memset(&io->over_script.lvar[i], 0, sizeof(SCRIPT_VAR));
retry2:
;
switch (avs->type)
{
case TYPE_L_TEXT:
strcpy(io->over_script.lvar[i].name, avs->name);
io->over_script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->over_script.lvar[i].ival);
io->over_script.lvar[i].type = TYPE_L_TEXT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
if (io->over_script.lvar[i].ival)
{
io->over_script.lvar[i].text = (char *) malloc(io->over_script.lvar[i].ival + 1);
if (!io->over_script.lvar[i].text) HERMES_Memory_Emergency_Out();
memset(io->over_script.lvar[i].text, 0, io->over_script.lvar[i].ival + 1);
memcpy(io->over_script.lvar[i].text, dat + pos, io->over_script.lvar[i].ival);
pos += io->over_script.lvar[i].ival;
io->over_script.lvar[i].ival = strlen(io->over_script.lvar[i].text) + 1;
}
else
{
io->over_script.lvar[i].text = NULL;
io->over_script.lvar[i].ival = 0;
}
break;
case TYPE_L_LONG:
strcpy(io->over_script.lvar[i].name, avs->name);
io->over_script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->over_script.lvar[i].ival);
io->over_script.lvar[i].type = TYPE_L_LONG;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
case TYPE_L_FLOAT:
strcpy(io->over_script.lvar[i].name, avs->name);
io->over_script.lvar[i].fval = avs->fval;
F2L(avs->fval, &io->over_script.lvar[i].ival);
io->over_script.lvar[i].type = TYPE_L_FLOAT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
default:
if ((avs->name[0] == '$') || (avs->name[0] == '£'))
{
avs->type = TYPE_L_TEXT;
goto retry2;
}
if ((avs->name[0] == '#') || (avs->name[0] == 's'))
{
avs->type = TYPE_L_LONG;
goto retry2;
}
if ((avs->name[0] == '&') || (avs->name[0] == '@'))
{
avs->type = TYPE_L_FLOAT;
goto retry2;
}
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
strcpy(io->script.lvar[i].name, avs->name);
io->script.lvar[i].fval = 0;
io->script.lvar[i].ival = 0;
io->script.lvar[i].type = TYPE_L_LONG;
ERRCOUNT++;
ass->nblvar = i;
goto corrupted;
break;
}
}
_Gaids[Gaids_Number]->weapon[0] = 0;
switch (ais->savesystem_type)
{
case TYPE_NPC:
ARX_CHANGELEVEL_NPC_IO_SAVE * as;
as = (ARX_CHANGELEVEL_NPC_IO_SAVE *)(dat + pos);
{
io->_npcdata->absorb = as->absorb;
io->_npcdata->aimtime = as->aimtime;
io->_npcdata->armor_class = as->armor_class;
io->_npcdata->behavior = as->behavior;
io->_npcdata->behavior_param = as->behavior_param;
io->_npcdata->collid_state = as->collid_state;
io->_npcdata->collid_time = as->collid_time;
io->_npcdata->cut = as->cut;
io->_npcdata->damages = as->damages;
io->_npcdata->detect = as->detect;
io->_npcdata->fightdecision = as->fightdecision;
strcpy(_Gaids[Gaids_Number]->weapon, as->id_weapon);
io->_npcdata->lastmouth = as->lastmouth;
io->_npcdata->life = as->life;
io->_npcdata->look_around_inc = as->look_around_inc;
io->_npcdata->mana = as->mana;
io->_npcdata->maxlife = as->maxlife;
io->_npcdata->maxmana = as->maxmana;
io->_npcdata->movemode = as->movemode;
io->_npcdata->moveproblem = as->moveproblem;
io->_npcdata->reachedtarget = as->reachedtarget;
io->_npcdata->speakpitch = as->speakpitch;
io->_npcdata->tactics = as->tactics;
io->_npcdata->tohit = as->tohit;
io->_npcdata->weaponinhand = as->weaponinhand;
strcpy(io->_npcdata->weaponname, as->weaponname);
io->_npcdata->weapontype = as->weapontype;
io->_npcdata->xpvalue = as->xpvalue;
memcpy(io->_npcdata->stacked, as->stacked, sizeof(IO_BEHAVIOR_DATA)*MAX_STACKED_BEHAVIOR);
for (long iii = 0; iii < MAX_STACKED_BEHAVIOR; iii++)
{
strcpy(_Gaids[Gaids_Number]->stackedtarget[iii], as->stackedtarget[iii]);
}
io->_npcdata->critical = as->critical;
io->_npcdata->reach = as->reach;
io->_npcdata->backstab_skill = as->backstab_skill;
io->_npcdata->poisonned = as->poisonned;
io->_npcdata->resist_poison = as->resist_poison;
io->_npcdata->resist_magic = as->resist_magic;
io->_npcdata->resist_fire = as->resist_fire;
io->_npcdata->strike_time = as->strike_time;
io->_npcdata->walk_start_time = as->walk_start_time;
io->_npcdata->aiming_start = as->aiming_start;
io->_npcdata->npcflags = as->npcflags;
io->_npcdata->fDetect = as->fDetect;
io->_npcdata->cuts = as->cuts;
memset(&io->_npcdata->pathfind, 0, sizeof(IO_PATHFIND));
io->_npcdata->pathfind.truetarget = as->pathfind.truetarget;
if (ais->saveflags & SAVEFLAGS_EXTRA_ROTATE)
{
if (io->_npcdata->ex_rotate == NULL)
{
io->_npcdata->ex_rotate = (EERIE_EXTRA_ROTATE *) malloc(sizeof(EERIE_EXTRA_ROTATE));
if (!io->_npcdata->ex_rotate) HERMES_Memory_Emergency_Out();
}
memcpy(io->_npcdata->ex_rotate, &as->ex_rotate, sizeof(EERIE_EXTRA_ROTATE));
}
io->_npcdata->blood_color = as->blood_color;
}
pos += sizeof(ARX_CHANGELEVEL_NPC_IO_SAVE);
break;
case TYPE_ITEM:
ARX_CHANGELEVEL_ITEM_IO_SAVE * ai;
ai = (ARX_CHANGELEVEL_ITEM_IO_SAVE *)(dat + pos);
io->_itemdata->price = ai->price;
io->_itemdata->count = ai->count;
io->_itemdata->maxcount = ai->maxcount;
io->_itemdata->food_value = ai->food_value;
io->_itemdata->stealvalue = ai->stealvalue;
io->_itemdata->playerstacksize = ai->playerstacksize;
io->_itemdata->LightValue = ai->LightValue;
if (ais->system_flags & SYSTEM_FLAG_EQUIPITEMDATA)
{
if (io->_itemdata->equipitem)
free(io->_itemdata->equipitem);
io->_itemdata->equipitem = (IO_EQUIPITEM *)malloc(sizeof(IO_EQUIPITEM));
memcpy(io->_itemdata->equipitem, &ai->equipitem, sizeof(IO_EQUIPITEM));
}
else io->_itemdata->equipitem = NULL;
pos += sizeof(ARX_CHANGELEVEL_ITEM_IO_SAVE);
break;
case TYPE_FIX:
ARX_CHANGELEVEL_FIX_IO_SAVE * af;
af = (ARX_CHANGELEVEL_FIX_IO_SAVE *)(dat + pos);
io->_fixdata->trapvalue = af->trapvalue;
pos += sizeof(ARX_CHANGELEVEL_FIX_IO_SAVE);
break;
case TYPE_CAMERA:
ARX_CHANGELEVEL_CAMERA_IO_SAVE * ac;
ac = (ARX_CHANGELEVEL_CAMERA_IO_SAVE *)(dat + pos);
memcpy(io->_camdata, &ac->cam, sizeof(EERIE_CAMERA));
pos += sizeof(ARX_CHANGELEVEL_CAMERA_IO_SAVE);
break;
case TYPE_MARKER:
ARX_CHANGELEVEL_MARKER_IO_SAVE * am;
am = (ARX_CHANGELEVEL_MARKER_IO_SAVE *)(dat + pos);
pos += sizeof(ARX_CHANGELEVEL_MARKER_IO_SAVE);
break;
}
if (ais->system_flags & SYSTEM_FLAG_INVENTORY)
{
memcpy(_Gaids[Gaids_Number], dat + pos,
sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE)
- SIZE_ID - SIZE_ID - MAX_LINKED_SAVE * SIZE_ID
- SIZE_ID * MAX_STACKED_BEHAVIOR);
pos += sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE);
if (io->inventory == NULL)
{
io->inventory = (void *) malloc(sizeof(INVENTORY_DATA));
if (!io->inventory) HERMES_Memory_Emergency_Out();
}
memset(io->inventory, 0, sizeof(INVENTORY_DATA));
}
else
{
if (io->inventory)
{
free(io->inventory);
io->inventory = NULL;
}
}
if (ais->system_flags & SYSTEM_FLAG_TWEAKER_INFO)
{
if (io->tweakerinfo)
free(io->tweakerinfo);
//{
io->tweakerinfo = (IO_TWEAKER_INFO *) malloc(sizeof(IO_TWEAKER_INFO));
if (!io->tweakerinfo) HERMES_Memory_Emergency_Out();
//}
memcpy(io->tweakerinfo, dat + pos, sizeof(IO_TWEAKER_INFO));
pos += sizeof(IO_TWEAKER_INFO);
}
if (io->iogroups) free(io->iogroups);
io->iogroups = NULL;
if (io->nb_iogroups > 0)
{
io->iogroups = (IO_GROUP_DATA *) malloc(sizeof(IO_GROUP_DATA) * io->nb_iogroups);
if (!io->iogroups) HERMES_Memory_Emergency_Out();
IO_GROUP_DATA * igd = (IO_GROUP_DATA *)(dat + pos);
memcpy(io->iogroups, igd, sizeof(IO_GROUP_DATA)*io->nb_iogroups);
pos += sizeof(IO_GROUP_DATA) * io->nb_iogroups;
}
io->Tweak_nb = ais->Tweak_nb;
if (io->Tweak_nb)
{
io->Tweaks = (TWEAK_INFO *)malloc(sizeof(TWEAK_INFO) * io->Tweak_nb);
if (!io->Tweaks) HERMES_Memory_Emergency_Out();
TWEAK_INFO * ti = (TWEAK_INFO *)(dat + pos);
pos += sizeof(TWEAK_INFO) * io->Tweak_nb;
memcpy(io->Tweaks, ti, sizeof(TWEAK_INFO)*io->Tweak_nb);
}
ARX_INTERACTIVE_APPLY_TWEAK_INFO(io);
if (io->obj)
{
io->obj->nblinked = ais->nb_linked;
if (io->obj->nblinked)
{
if (io->obj->linked)
free(io->obj->linked);
io->obj->linked = (EERIE_LINKED *) malloc(sizeof(EERIE_LINKED) * (io->obj->nblinked));
if (!io->obj->linked) HERMES_Memory_Emergency_Out();
for (long n = 0; n < ais->nb_linked; n++)
{
io->obj->linked[n].lgroup = ais->linked_data[n].lgroup;
io->obj->linked[n].lidx = ais->linked_data[n].lidx;
io->obj->linked[n].lidx2 = ais->linked_data[n].lidx2;
memcpy(&io->obj->linked[n].modinfo, &ais->linked_data[n].modinfo, sizeof(EERIE_MOD_INFO));
strcpy(_Gaids[Gaids_Number]->linked_id[n], ais->linked_data[n].linked_id);
io->obj->linked[n].io = NULL;
io->obj->linked[n].obj = NULL;
}
}
}
long hidegore;
if ((io->ioflags & IO_NPC)
&& (io->_npcdata->life > 0.f))
hidegore = 1;
else
hidegore = 0;
ARX_INTERACTIVE_HideGore(io, hidegore);
}
else
{
char temp[512];
sprintf(temp, "CHANGELEVEL Error: Unable to load %s", ident);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(temp);
}
free(dat);
CONVERT_CREATED = 1;
if (NEED_LOG)
{
char temp[256];
sprintf(temp, "--> After ARX_CHANGELEVEL_Pop_IO(%s)", ident);
LogData(temp);
}
return GetInterNum(tmp);
corrupted:
char cstring[256];
sprintf(cstring, "Save File Is Corrupted\nTrying to Fix %s", ident);
ShowPopup(cstring);//"Save file is corrupted.");
free(dat);
io->inventory = NULL;
RestoreInitialIOStatusOfIO(io);
SendInitScriptEvent(io);
return idx;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_PopAllIO(ARX_CHANGELEVEL_INDEX * asi)
{
float increment = 0;
if (asi->nb_inter > 0)
{
increment = (60.f / (float)asi->nb_inter);
}
else
{
PROGRESS_BAR_COUNT += 60;
LoadLevelScreen();
}
for (long i = 0; i < asi->nb_inter; i++)
{
if ((i == 4) || (i == 62))
{
i = i;
}
PROGRESS_BAR_COUNT += increment;
LoadLevelScreen();
char tempo[256];
sprintf(tempo, "%s_%04d", GetName(idx_io[i].filename), idx_io[i].ident);
ARX_CHANGELEVEL_Pop_IO(tempo);
}
return 1;
}
extern void GetIOCyl(INTERACTIVE_OBJ * io, EERIE_CYLINDER * cyl);
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_PopAllIO_FINISH(ARX_CHANGELEVEL_INDEX * asi, long reloadflag)
{
unsigned char * treated = (unsigned char *) malloc(sizeof(unsigned char) * MAX_IO_SAVELOAD);
if (!treated) HERMES_Memory_Emergency_Out();
memset(treated, 0, sizeof(unsigned char)*MAX_IO_SAVELOAD);
long converted = 1;
while (converted)
{
converted = 0;
for (long it = 1; it < MAX_IO_SAVELOAD; it++)
{
if (it < inter.nbmax)
{
INTERACTIVE_OBJ * io = inter.iobj[it];
if ((io) && (treated[it] == 0))
{
treated[it] = 1;
ARX_CHANGELEVEL_INVENTORY_DATA_SAVE * aids = _Gaids[it];
if (_Gaids[it])
{
if (io->inventory)
{
INVENTORY_DATA * inv = (INVENTORY_DATA *)io->inventory;
inv->io = ConvertToValidIO(aids->io);
converted += CONVERT_CREATED;
if ((aids->sizex != 3)
|| (aids->sizey != 11))
{
inv->sizex = 3;
inv->sizey = 11;
for (long m = 0; m < inv->sizex; m++)
for (long n = 0; n < inv->sizey; n++)
{
inv->slot[m][n].io = NULL;
inv->slot[m][n].show = 0;
}
}
else
{
inv->sizex = aids->sizex;
inv->sizey = aids->sizey;
for (long m = 0; m < inv->sizex; m++)
for (long n = 0; n < inv->sizey; n++)
{
inv->slot[m][n].io = ConvertToValidIO(aids->slot_io[m][n]);
converted += CONVERT_CREATED;
inv->slot[m][n].show = aids->slot_show[m][n];
}
}
}
if ((io->obj) && (io->obj->nblinked))
{
for (long n = 0; n < io->obj->nblinked; n++)
{
INTERACTIVE_OBJ * iooo = ConvertToValidIO(aids->linked_id[n]);
if (iooo)
{
io->obj->linked[n].io = iooo;
io->obj->linked[n].obj = iooo->obj;
}
}
}
if (io->ioflags & IO_NPC)
{
io->_npcdata->weapon = ConvertToValidIO(aids->weapon);
converted += CONVERT_CREATED;
if (io->_npcdata->weaponinhand == 1)
SetWeapon_On(io);
else SetWeapon_Back(io);
}
if (!stricmp(aids->targetinfo, "NONE")) io->targetinfo = -1;
else if (!stricmp(aids->targetinfo, "SELF")) io->targetinfo = -2;
else if (!stricmp(aids->targetinfo, "PLAYER")) io->targetinfo = 0;
else
io->targetinfo = GetInterNum(ConvertToValidIO(aids->targetinfo));
if (io->ioflags & IO_NPC)
{
for (long iii = 0; iii < MAX_STACKED_BEHAVIOR; iii++)
{
if (!stricmp(aids->stackedtarget[iii], "NONE")) io->_npcdata->stacked[iii].target = -1;
else if (!stricmp(aids->stackedtarget[iii], "SELF")) io->_npcdata->stacked[iii].target = -2;
else if (!stricmp(aids->stackedtarget[iii], "PLAYER")) io->_npcdata->stacked[iii].target = 0;
else
io->_npcdata->stacked[iii].target = GetInterNum(ConvertToValidIO(aids->stackedtarget[iii]));
}
}
if (io->ioflags & IO_NPC)
if (io->_npcdata->behavior == BEHAVIOUR_NONE)
io->targetinfo = -1;
}
}
}
}
}
free(treated);
if (reloadflag)
{
for (long i = 0; i < inter.nbmax; i++)
{
if (inter.iobj[i])
{
if (inter.iobj[i]->script.data != NULL)
{
SendScriptEvent(&inter.iobj[i]->script, SM_RELOAD, "CHANGE", inter.iobj[i], NULL);
}
if (inter.iobj[i]
&& inter.iobj[i]->over_script.data)
{
SendScriptEvent(&inter.iobj[i]->over_script, SM_RELOAD, "CHANGE", inter.iobj[i], NULL);
}
if (inter.iobj[i]
&& (inter.iobj[i]->ioflags & IO_NPC))
{
if (ValidIONum(inter.iobj[i]->targetinfo))
{
if (inter.iobj[i]->_npcdata->behavior != BEHAVIOUR_NONE)
{
GetIOCyl(inter.iobj[i], &inter.iobj[i]->physics.cyl);
GetTargetPos(inter.iobj[i]);
ARX_NPC_LaunchPathfind(inter.iobj[i], inter.iobj[i]->targetinfo); //io->_npcdata->pathfind.truetarget);
}
}
}
}
}
}
else if (_FIRSTTIME)
{
for (long i = 0; i < inter.nbmax; i++)
{
if (inter.iobj[i])
{
if (inter.iobj[i]->script.data)
{
SendScriptEvent(&inter.iobj[i]->script, SM_INIT, "", inter.iobj[i], NULL);
}
if (inter.iobj[i]
&& inter.iobj[i]->over_script.data)
{
SendScriptEvent(&inter.iobj[i]->over_script, SM_INIT, "", inter.iobj[i], NULL);
}
if (inter.iobj[i]
&& inter.iobj[i]->script.data)
{
SendScriptEvent(&inter.iobj[i]->script, SM_INITEND, "", inter.iobj[i], NULL);
}
if (inter.iobj[i]
&& inter.iobj[i]->over_script.data)
{
SendScriptEvent(&inter.iobj[i]->over_script, SM_INITEND, "", inter.iobj[i], NULL);
}
}
}
}
else
{
for (long i = 0; i < inter.nbmax; i++)
{
if (inter.iobj[i])
{
if (inter.iobj[i]
&& (inter.iobj[i]->ioflags & IO_NPC))
{
if (ValidIONum(inter.iobj[i]->targetinfo))
{
if (inter.iobj[i]->_npcdata->behavior != BEHAVIOUR_NONE)
{
GetIOCyl(inter.iobj[i], &inter.iobj[i]->physics.cyl);
GetTargetPos(inter.iobj[i]);
ARX_NPC_LaunchPathfind(inter.iobj[i], inter.iobj[i]->targetinfo); //io->_npcdata->pathfind.truetarget);
}
}
}
}
}
}
return 1;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Pop_Globals()
{
ARX_CHANGELEVEL_SAVE_GLOBALS * acsg;
unsigned char * dat;
long pos = 0;
char loadfile[256];
long size;
char _error[256];
ARX_SCRIPT_Free_All_Global_Variables();
sprintf(loadfile, "Globals.sav");
size = _pSaveBlock->GetSize(loadfile);
if (size < 0)
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(_error);
return -1;
}
char * compressed = (char *) GetStdBuffer(size);
if (!compressed) HERMES_Memory_Emergency_Out();
if (!_pSaveBlock->Read(loadfile, (char *)compressed))
{
sprintf(_error, "Unable to Open %s for Read...", loadfile);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(_error);
return -1;
}
for (long i = 0; i < size; i += 2)
{
compressed[i] = ~compressed[i];
}
long ssize = size;
dat = (unsigned char *)STD_Explode(compressed, ssize, &size);
acsg = (ARX_CHANGELEVEL_SAVE_GLOBALS *)(dat);
pos += sizeof(ARX_CHANGELEVEL_SAVE_GLOBALS);
if (acsg->version != ARX_GAMESAVE_VERSION)
{
free(dat);
sprintf(_error, "Invalid version: %s...", loadfile);
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup(_error);
return -1;
}
if (acsg->nb_globals > 0)
{
svar = (SCRIPT_VAR *) malloc(sizeof(SCRIPT_VAR) * acsg->nb_globals);
if (!svar) HERMES_Memory_Emergency_Out();
}
else svar = NULL;
NB_GLOBALS = acsg->nb_globals;
for (int i = 0; i < NB_GLOBALS; i++)
{
ARX_CHANGELEVEL_VARIABLE_SAVE * av = (ARX_CHANGELEVEL_VARIABLE_SAVE *)(dat + pos);
switch (av->type)
{
case TYPE_G_TEXT:
strcpy(svar[i].name, av->name);
svar[i].fval = av->fval;
F2L(av->fval, &svar[i].ival);
svar[i].type = TYPE_G_TEXT;
if (svar[i].ival)
{
svar[i].text = (char *) malloc(svar[i].ival + 1);
memset(svar[i].text, 0, svar[i].ival + 1);
if (!svar[i].text) HERMES_Memory_Emergency_Out();
memcpy(svar[i].text, dat + pos + sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE), svar[i].ival);
if (svar[i].text[0] == 'Ì')
svar[i].text[0] = 0;
}
else
svar[i].text = NULL;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
if (svar[i].text)
svar[i].ival = strlen(svar[i].text) + 1;
else
svar[i].ival = 0;
pos += (long)av->fval;
break;
case TYPE_G_LONG:
strcpy(svar[i].name, av->name);
F2L(av->fval, &svar[i].ival);
svar[i].fval = av->fval;
svar[i].text = NULL;
svar[i].type = TYPE_G_LONG;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
case TYPE_G_FLOAT:
strcpy(svar[i].name, av->name);
F2L(av->fval, &svar[i].ival);
svar[i].fval = av->fval;
svar[i].text = NULL;
svar[i].type = TYPE_G_FLOAT;
pos += sizeof(ARX_CHANGELEVEL_VARIABLE_SAVE);
break;
default:
{
//at this level is strange
svar[i].fval = 0.f;
svar[i].text = NULL;
svar[i].type = TYPE_G_TEXT;
}
break;
}
}
free(dat);
return 1;
}
//-----------------------------------------------------------------------------
void ReleaseGaids()
{
for (long i = 0; i < inter.nbmax; i++)
{
if (_Gaids[i] != NULL)
free(_Gaids[i]);
}
free(_Gaids);
_Gaids = NULL;
}
extern long NODIRCREATION;
#include
#include "DanaeDlg.h"
void ReplaceSpecifics(char * text);
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_PopLevel(long instance, long reloadflag)
{
DANAE_ReleaseAllDatasDynamic();
LogData("Before ARX_CHANGELEVEL_PopLevel Alloc'n'Free");
if (_Gaids) ReleaseGaids();
_Gaids = (ARX_CHANGELEVEL_INVENTORY_DATA_SAVE **) malloc(sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE *) * MAX_IO_SAVELOAD);
if (!_Gaids) HERMES_Memory_Emergency_Out();
memset(_Gaids, 0, sizeof(ARX_CHANGELEVEL_INVENTORY_DATA_SAVE *)*MAX_IO_SAVELOAD);
ARX_CHANGELEVEL_INDEX asi;
ARX_CHANGELEVEL_PLAYER asp;
CURRENT_GAME_INSTANCE = instance;
ARX_CHANGELEVEL_MakePath();
if (!DirectoryExist(CurGamePath))
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load this game: Directory Not Found");
RELOADING = 0;
ReleaseGaids();
return -1;
}
LogData("After ARX_CHANGELEVEL_PopLevel Alloc'n'Free");
// Clears All Scene contents...
LogData("Before DANAE ClearAll");
DanaeClearAll();
LogData("After DANAE ClearAll");
ARX_TIME_Pause();
ARX_TIME_Force_Time_Restore(ARX_CHANGELEVEL_DesiredTime);
FORCE_TIME_RESTORE = ARX_CHANGELEVEL_DesiredTime;
// Now we can load our things...
char loadfile[256];
long FirstTime;
sprintf(loadfile, "lvl%03d.sav", instance);
LogData("Before Saveblock Access");
// Open Saveblock for read
char sfile[256];
sprintf(sfile, "%sGsave.sav", CurGamePath);
_pSaveBlock = new CSaveBlock(sfile);
_pSaveBlock->BeginRead();
LogData("After Saveblock Access");
PROGRESS_BAR_COUNT += 2.f;
LoadLevelScreen(GDevice, instance);
// first time in this level ?
if (!FileExist(sfile))
{
FirstTime = 1;
FORBID_SCRIPT_IO_CREATION = 0;
NO_PLAYER_POSITION_RESET = 0;
}
else if (_pSaveBlock->GetSize(loadfile) < 0)
{
FirstTime = 1;
FORBID_SCRIPT_IO_CREATION = 0;
NO_PLAYER_POSITION_RESET = 0;
}
else
{
FirstTime = 0;
FORBID_SCRIPT_IO_CREATION = 1;
NO_PLAYER_POSITION_RESET = 1;
}
_FIRSTTIME = FirstTime;
NEW_LEVEL = instance;
if (!FirstTime)
{
LogData("Before ARX_CHANGELEVEL_Pop_Index");
if (ARX_CHANGELEVEL_Pop_Index(&asi, instance) != 1)
{
FreeStdBuffer();
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load Index data");
ARX_TIME_UnPause();
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
ReleaseTio();
RELOADING = 0;
ReleaseGaids();
FORBID_SCRIPT_IO_CREATION = 0;
return -1;
}
LogData("After ARX_CHANGELEVEL_Pop_Index");
if (asi.version != ARX_GAMESAVE_VERSION)
{
FreeStdBuffer();
ShowPopup("Invalid Save Version...");
ARX_TIME_UnPause();
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
ReleaseTio();
RELOADING = 0;
ReleaseGaids();
FORBID_SCRIPT_IO_CREATION = 0;
return -1;
}
idx_io_nb = asi.nb_inter;
}
else
{
idx_io_nb = 0;
idx_io = NULL;
}
PROGRESS_BAR_COUNT += 2.f;
LoadLevelScreen(GDevice, instance);
LogData("Before ARX_CHANGELEVEL_Pop_Level");
if (ARX_CHANGELEVEL_Pop_Level(&asi, instance, FirstTime) != 1)
{
FreeStdBuffer();
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load Level data");
ARX_TIME_UnPause();
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
ReleaseTio();
RELOADING = 0;
ReleaseGaids();
FORBID_SCRIPT_IO_CREATION = 0;
return -1;
}
LogData("After ARX_CHANGELEVEL_Pop_Index");
PROGRESS_BAR_COUNT += 20.f;
LoadLevelScreen(GDevice, instance);
if (FirstTime)
{
ARX_CHECK_ULONG(ARX_CHANGELEVEL_DesiredTime);
unsigned long ulDTime = ARX_CLEAN_WARN_CAST_ULONG(ARX_CHANGELEVEL_DesiredTime);
for (long i = 0; i < MAX_TIMER_SCRIPT; i++)
{
if (scr_timer[i].exist)
{
scr_timer[i].tim = ulDTime;
}
}
}
if (!FirstTime)
{
LogData("Before ARX_CHANGELEVEL_PopAllIO");
if (ARX_CHANGELEVEL_PopAllIO(&asi) != 1)
{
FreeStdBuffer();
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load IO data");
ARX_TIME_UnPause();
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
ReleaseTio();
RELOADING = 0;
ReleaseGaids();
FORBID_SCRIPT_IO_CREATION = 0;
return -1;
}
LogData("After ARX_CHANGELEVEL_PopAllIO");
}
PROGRESS_BAR_COUNT += 20.f;
LoadLevelScreen(GDevice, instance);
LogData("Before ARX_CHANGELEVEL_Pop_Player");
if (ARX_CHANGELEVEL_Pop_Player(&asi, &asp) != 1)
{
FreeStdBuffer();
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Cannot Load Player data");
ARX_TIME_UnPause();
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
ReleaseTio();
RELOADING = 0;
ReleaseGaids();
FORBID_SCRIPT_IO_CREATION = 0;
return -1;
}
LogData("After ARX_CHANGELEVEL_Pop_Player");
PROGRESS_BAR_COUNT += 10.f;
LoadLevelScreen();
LogData("Before Misc Code");
// Restoring Player equipment...
player.equipsecondaryIO = ConvertToValidIO(asp.equipsecondaryIO);
player.equipshieldIO = ConvertToValidIO(asp.equipshieldIO);
player.leftIO = ConvertToValidIO(asp.leftIO);
player.rightIO = ConvertToValidIO(asp.rightIO);
CURRENT_TORCH = ConvertToValidIO(asp.curtorch);
PROGRESS_BAR_COUNT += 1.f;
LoadLevelScreen();
for (int iNbBag = 0; iNbBag < 3; iNbBag++)
{
for (long m = 0; m < INVENTORY_Y; m++)
for (long n = 0; n < INVENTORY_X; n++)
{
inventory[iNbBag][n][m].io = ConvertToValidIO(asp.id_inventory[iNbBag][n][m]);
inventory[iNbBag][n][m].show = asp.inventory_show[iNbBag][n][m];
}
}
for (long i = 0; i < MAX_EQUIPED; i++)
{
player.equiped[i] = (short)GetInterNum(ConvertToValidIO(asp.equiped[i]));
if ((player.equiped[i] > 0) && (ValidIONum(player.equiped[i])))
inter.iobj[player.equiped[i]]->level = (short)instance;
else player.equiped[i] = 0;
}
PROGRESS_BAR_COUNT += 2.f;
LoadLevelScreen();
LogData("After Misc Code");
LogData("Before ARX_CHANGELEVEL_PopAllIO_FINISH");
// Restoring all Missing Objects required by other objects...
ARX_CHANGELEVEL_PopAllIO_FINISH(&asi, reloadflag);
LogData("After ARX_CHANGELEVEL_PopAllIO_FINISH");
PROGRESS_BAR_COUNT += 15.f;
LoadLevelScreen();
ReleaseGaids();
PROGRESS_BAR_COUNT += 3.f;
LoadLevelScreen();
if (!FirstTime)
{
LogData("Before ARX_CHANGELEVEL_Pop_Zones_n_Lights");
ARX_CHANGELEVEL_Pop_Zones_n_Lights(&asi, instance);
LogData("After ARX_CHANGELEVEL_Pop_Zones_n_Lights");
}
PROGRESS_BAR_COUNT += 1.f;
LoadLevelScreen();
LogData("Before Player Misc Init");
ForcePlayerInventoryObjectLevel(instance);
ARX_EQUIPMENT_RecreatePlayerMesh();
PROGRESS_BAR_COUNT += 1.f;
LoadLevelScreen();
ReleaseTio();
ARX_TIME_Force_Time_Restore(ARX_CHANGELEVEL_DesiredTime);
NO_TIME_INIT = 1;
FORCE_TIME_RESTORE = ARX_CHANGELEVEL_DesiredTime;
LogData("After Player Misc Init");
LogData("Before Memory Release");
if (idx_io)
free(idx_io);
idx_io = NULL;
if (index_variable)
free(index_variable);
index_variable = NULL;
idx_io_nb = 0;
RELOADING = 0;
FORBID_SCRIPT_IO_CREATION = 0;
NO_TIME_INIT = 1;
FreeStdBuffer();
LogData("After Memory Release");
LogData("Before SaveBlock Release");
_pSaveBlock->EndRead();
delete _pSaveBlock;
_pSaveBlock = NULL;
LogData("After SaveBlock Release");
LogData("Before Final Inits");
HERO_SHOW_1ST = -1;
if (EXTERNALVIEW)
{
ARX_INTERACTIVE_Show_Hide_1st(inter.iobj[0], 0);
}
if (!EXTERNALVIEW)
{
ARX_INTERACTIVE_Show_Hide_1st(inter.iobj[0], 1);
}
ARX_INTERACTIVE_HideGore(inter.iobj[0], 1);
TRUE_PLAYER_MOUSELOOK_ON = 0;
player.Interface &= ~INTER_COMBATMODE;
PROGRESS_BAR_COUNT += 1.f;
LoadLevelScreen();
LogData("After Final Inits");
return 1;
}
//-----------------------------------------------------------------------------
// copie un rep (récursif sous reps) dans un autre en créant les reps
// écrase les fichiers pour les mettre à jour
void CopyDirectory(char * _lpszSrc, char * _lpszDest)
{
CreateDirectory(_lpszDest, NULL);
// WIN32_FIND_DATA FindFileData;
HANDLE hFind;
printf("Target file is %s.\n", _lpszSrc);
char path[256];
ZeroMemory(path, 256);
strcpy(path, _lpszSrc);
strcat(path, "*.*");
char tTemp[sizeof(WIN32_FIND_DATA)+2];
WIN32_FIND_DATA * FindFileData = (WIN32_FIND_DATA *)tTemp;
hFind = FindFirstFile(path, FindFileData);
do
{
if (hFind != INVALID_HANDLE_VALUE)
{
if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (strcmp(FindFileData->cFileName, ".") == 0) continue;
if (strcmp(FindFileData->cFileName, "..") == 0) continue;
char s[256];
char d[256];
ZeroMemory(s, 256);
ZeroMemory(d, 256);
strcpy(s, _lpszSrc);
strcpy(d, _lpszDest);
strcat(s, FindFileData->cFileName);
strcat(d, FindFileData->cFileName);
strcat(s, "\\");
strcat(d, "\\");
CopyDirectory(s, d);
}
else
{
char s[256];
char d[256];
ZeroMemory(s, 256);
ZeroMemory(d, 256);
strcpy(s, _lpszSrc);
strcpy(d, _lpszDest);
strcat(s, FindFileData->cFileName);
strcat(d, FindFileData->cFileName);
CopyFile(s, d, false);
}
}
}
while (FindNextFile(hFind, FindFileData) > 0);
if (hFind)
FindClose(hFind);
}
//-----------------------------------------------------------------------------
///////////////////////// SAVE LOAD
long ARX_CHANGELEVEL_Save(long instance, char * name)
{
ARX_TIME_Pause();
if (instance <= 0)
{
ARX_GAMESAVE_CreateNewInstance();
instance = CURRENT_GAME_INSTANCE;
}
CURRENT_GAME_INSTANCE = instance;
if (instance == -1)
{
// fatality...
ShowPopup("Internal Non-Fatal Error");
return 0;
}
if (CURRENTLEVEL == -1)
{
// fatality...
ShowPopup("Internal Non-Fatal Error");
return 0;
}
ARX_SCRIPT_EventStackExecuteAll();
// fill GameSavePath with our savepath.
ARX_GAMESAVE_MakePath();
// Erase All directory content if overwriting a game
CreateDirectory(GameSavePath, NULL);
if (SecondaryInventory != NULL)
{
INTERACTIVE_OBJ * io = (INTERACTIVE_OBJ *)SecondaryInventory->io;
if (io != NULL)
{
InventoryDir = -1;
SendIOScriptEvent(io, SM_INVENTORY2_CLOSE, "");
TSecondaryInventory = SecondaryInventory;
SecondaryInventory = NULL;
}
}
ARX_CHANGELEVEL_MakePath();
ARX_CHANGELEVEL_PushLevel(CURRENTLEVEL, CURRENTLEVEL);
KillAllDirectory(GameSavePath);
CopyDirectory(CurGamePath, GameSavePath);
//on copie le fichier temporaire bmp dans le repertoire
char tcSrc[256];
char tcDst[256];
sprintf(tcSrc, "%sSCT_0.BMP", Project.workingdir);
sprintf(tcDst, "%sGSAVE.BMP", GameSavePath);
CopyFile(tcSrc, tcDst, FALSE);
DeleteFile(tcSrc);
ARX_CHANGELEVEL_PLAYER_LEVEL_DATA pld;
memset(&pld, 0, sizeof(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA));
pld.level = CURRENTLEVEL;
strcpy(pld.name, name);
pld.version = ARX_GAMESAVE_VERSION;
pld.time = ARX_TIME_GetUL(); //treat warning C4244 conversion from 'float' to 'unsigned long''
ARX_CHANGELEVEL_Set_Player_LevelData(&pld, GameSavePath);
ARX_TIME_UnPause();
return 1;
}
//-----------------------------------------------------------------------------
long ARX_CHANGELEVEL_Set_Player_LevelData(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA * pld, char * path)
{
char sfile[256];
sprintf(sfile, "%sGsave.sav", path);
_pSaveBlock = new CSaveBlock(sfile);
if (!_pSaveBlock->BeginSave(true, 1)) return -1;
if (!DirectoryExist(path)) return -1;
unsigned char * dat;
dat = (unsigned char *) malloc(sizeof(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA));
if (!dat) HERMES_Memory_Emergency_Out();
memcpy(dat, pld, sizeof(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA));
long pos = sizeof(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA);
char savefile[256];
sprintf(savefile, "pld.sav");
char * compressed = NULL;
long cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
for (long i = 0; i < cpr_pos; i += 2)
compressed[i] = ~compressed[i];
_pSaveBlock->Save(savefile, compressed, cpr_pos);
free(compressed);
_pSaveBlock->EndSave();
delete _pSaveBlock;
_pSaveBlock = 0;
free(dat);
return 1;
}
//------------------------------------------------------------------------------
// ARX_CHANGELEVEL_Get_Player_LevelData: Retreives Player Level Data
// VERIFIED: Cyril 30/11/2001
//------------------------------------------------------------------------------
long ARX_CHANGELEVEL_Get_Player_LevelData(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA * pld, char * path)
{
// Checks For Directory
if (!DirectoryExist(path)) return -1;
char loadfile[256];
char _error[256];
long size;
unsigned char * dat;
// Open Save Block
char sfile[256];
sprintf(sfile, "%sGsave.sav", path);
_pSaveBlock = new CSaveBlock(sfile);
if (!_pSaveBlock->BeginRead()) return -1;
// Get Size
sprintf(loadfile, "pld.sav");
size = _pSaveBlock->GetSize(loadfile);
// Checks for Void/Invalid File
if (size <= 0)
{
sprintf(_error, "Unable to Open %s for Read1...", loadfile);
ShowPopup(_error);
_pSaveBlock->EndRead();
delete _pSaveBlock;
_pSaveBlock = 0;
return -1;
}
// Allocate Necessary Size
char * compressed = (char *) malloc(size);
if (!compressed) HERMES_Memory_Emergency_Out();
// Read Block
if (!_pSaveBlock->Read(loadfile, (char *)compressed))
{
free(compressed);
sprintf(_error, "Unable to Open %s for Read2...", loadfile);
ShowPopup(_error);
_pSaveBlock->EndRead();
delete _pSaveBlock;
_pSaveBlock = 0;
return -1;
}
// Un-Crypt
for (long i = 0; i < size; i += 2)
compressed[i] = ~compressed[i];
// Explode File
long ssize = size;
dat = (unsigned char *)STD_Explode(compressed, ssize, &size); //pos,&cpr_pos);
free(compressed);
if (dat == NULL)
{
sprintf(_error, "Unable to Explode %s...", loadfile);
ShowPopup(_error);
_pSaveBlock->EndRead();
delete _pSaveBlock;
_pSaveBlock = 0;
return -1;
}
// Finishes Read
_pSaveBlock->EndRead();
delete _pSaveBlock;
_pSaveBlock = 0;
// Stores Data in pld
memcpy(pld, dat, sizeof(ARX_CHANGELEVEL_PLAYER_LEVEL_DATA));
if (pld->version != ARX_GAMESAVE_VERSION)
{
ShowPopup("Invalid GameSave Version");
free(dat);
return -1;
}
// Release Data
free(dat);
return 1;
}
long DONT_CLEAR_SCENE;
extern long STARTED_A_GAME;
//------------------------------------------------------------------------------
// ARX_CHANGELEVEL_Load: Load a GameSave
//------------------------------------------------------------------------------
long ARX_CHANGELEVEL_Load(long instance)
{
LogData("-----------------------------------");
HERMES_DATE_TIME hdt;
GetDate(&hdt);
if (NEED_LOG)
{
LogData("ARX_CHANGELEVEL_Load");
char tex[256];
sprintf(tex, "Date: %02d/%02d/%d Time: %dh%d", hdt.days, hdt.months, hdt.years, hdt.hours, hdt.mins);
LogData(tex);
}
iTimeToDrawD7 = -3000;
PROGRESS_BAR_TOTAL = 238;
OLD_PROGRESS_BAR_COUNT = PROGRESS_BAR_COUNT = 0;
// Forbid Saving
FORBID_SAVE = 1;
ARX_TIME_Pause();
// Checks Instance
if (instance <= -1)
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Internal Non-Fatal Error");
return -1;
}
// Checks/Create GameSavePath
CURRENT_GAME_INSTANCE = instance;
ARX_GAMESAVE_MakePath();
if (!DirectoryExist(GameSavePath))
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Unknown SavePath");
return -1;
}
// Empty Directory
ARX_CHANGELEVEL_MakePath();
KillAllDirectory(CurGamePath);
CreateDirectory(CurGamePath, NULL);
// Copy SavePath to Current Game
CopyDirectory(GameSavePath, CurGamePath);
// Retrieves Player LevelData
ARX_CHANGELEVEL_PLAYER_LEVEL_DATA pld;
if (ARX_CHANGELEVEL_Get_Player_LevelData(&pld, CurGamePath) == 1)
{
PROGRESS_BAR_COUNT += 2.f;
LoadLevelScreen(GDevice, pld.level);
if (pld.level == CURRENTLEVEL)
DONT_CLEAR_SCENE = 1;
else
DONT_CLEAR_SCENE = 0;
float fPldTime = ARX_CLEAN_WARN_CAST_FLOAT(pld.time);
DanaeClearLevel();
PROGRESS_BAR_COUNT += 2.f;
LoadLevelScreen(GDevice, pld.level);
CURRENTLEVEL = pld.level;
ARX_CHANGELEVEL_DesiredTime = fPldTime;
ARX_CHANGELEVEL_PopLevel(pld.level, 0);
FreeStdBuffer();
ARX_TIME_Force_Time_Restore(fPldTime);
NO_TIME_INIT = 1;
FORCE_TIME_RESTORE = fPldTime;
DONT_CLEAR_SCENE = 0;
}
else
{
if (!FOR_EXTERNAL_PEOPLE)
ShowPopup("Error Loading Level...");
return -1;
}
STARTED_A_GAME = 1;
BLOCK_PLAYER_CONTROLS = 0;
player.Interface &= ~INTER_COMBATMODE;
if (inter.iobj[0]) inter.iobj[0]->animlayer[1].cur_anim = NULL;
JUST_RELOADED = 1;
return 1;
}
//------------------------------------------------------------------------------
// ARX_CHANGELEVEL_GetInfo: Retreives Name & Time of a Saved game in "path"
//------------------------------------------------------------------------------
long ARX_CHANGELEVEL_GetInfo(char * path, char * name, float * version, long * level, unsigned long * time)
{
if ((!path) || (!name) || (!version) || (!level) || (!time)) return -1;
ARX_CHANGELEVEL_PLAYER_LEVEL_DATA pld;
if (ARX_CHANGELEVEL_Get_Player_LevelData(&pld, path) == 1)
{
strcpy(name, pld.name);
*version = pld.version;
*level = pld.level;
*time = (pld.time / 1000);
return 1;
}
else
{
strcpy(name, "Invalid Save...");
*time = 0;
*level = 0;
*version = 0;
return -1;
}
}
//------------------------------------------------------------------------------