diff options
Diffstat (limited to 'DTObjectSerializing.c')
| -rw-r--r-- | DTObjectSerializing.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/DTObjectSerializing.c b/DTObjectSerializing.c new file mode 100644 index 0000000..bd68ddc --- /dev/null +++ b/DTObjectSerializing.c @@ -0,0 +1,406 @@ +#strict 2 + +static const Object_Status = 0; +static const Object_Name = 1; +static const Object_Owner = 2; +static const Object_Controller = 3; +static const Object_Killer = 4; +static const Object_Category = 5; +static const Object_Position = 6; +static const Object_Speed = 7; +static const Object_Con = 8; +static const Object_OwnMass = 9; +static const Object_Damage = 10; +static const Object_Energy = 11; +static const Object_MagicEnergy = 12; +static const Object_Alive = 13; +static const Object_Breath = 14; +static const Object_ColorDw = 15; +static const Object_Shape = 16; +static const Object_Vertices = 17; +static const Object_SolidMask = 18; +static const Object_Picture = 19; +static const Object_Entrance = 20; +static const Object_Physicals = 21; +static const Object_Action = 22; +static const Object_Components = 23; +static const Object_Contents = 24; +static const Object_PlrViewRange = 25; +static const Object_Visibility = 26; +static const Object_BlitMode = 27; +static const Object_CrewEnabled = 28; +static const Object_ObjectLayer = 29; +static const Object_Locals = 30; +static const Object_Graphics = 31; +static const Object_Effects = 32; +static const Object_ID = 33; +static const Object_ContactDensity = 34; +static const Object_Dir = 35; +static const Object_ComDir = 36; +static const Object_Origin = 37; +static const Object_Custom = 38; +static const Object_Count = 39; +//_enum(Object_, Status, Name, Owner, Controller, Killer, Category, Position, Speed, Con, OwnMass, Damage, Energy, MagicEnergy, Alive, Breath, ColorDw, Shape, Vertices, SolidMask, Picture, Entrance, Physicals, Action, Components, Contents, PlrViewRange, Visibility, BlitMode, CrewEnabled, ObjectLayer, Locals, Graphics, Effects, ID, ContactDensity, Dir, ComDir, Origin, Custom, Count) +// DONT KNOW: OnFire, Commands + +global func& LocalX(name, object obj) +{ + obj = obj || this; + if(GetType(name) == C4V_String) + { + return LocalN(name, obj); + } + else + { + return Local(name, obj); + } +} + +global func GetEffectVarCount(object target, int effectNumber) // WARNING: this could eventually be wrong (with a very very small probability) when some EffectVars are set right coincidentally +{ // based on and inspired by C4Effect::CompileFunc + var name = GetEffect(0, target, effectNumber, 1); + var prio = GetEffect(0, target, effectNumber, 2); + var timer = GetEffect(0, target, effectNumber, 3); + var lifeTime = GetEffect(0, target, effectNumber, 6); + + if(!name) + { + return -1; + } + + // determine offset for this effect within GetObjectVal + for(var i = 0; ; ++i) + { + if(GetObjectVal("Effects", 0, target, i) == name && GetObjectVal("Effects", 0, target, i + 1) == effectNumber && GetObjectVal("Effects", 0, target, i + 2) == prio && GetObjectVal("Effects", 0, target, i + 3) == lifeTime && GetObjectVal("Effects", 0, target, i + 4) == timer) + { + var count = GetObjectVal("Effects", 0, target, i + 7); + if(count == 1) + { + var nextEffectName = GetObjectVal("Effects", 0, target, i + 8); + if(GetType(nextEffectName) == C4V_String) + { + var nextNumber = GetObjectVal("Effects", 0, target, i + 9); + if(GetType(nextNumber) == C4V_Int && GetEffect(0, target, nextNumber, 1) == nextEffectName) + { + return 0; + } + } + + } + return GetType(count) == C4V_Int && count; + } + } +} + +global func GetObjectSaveData(object obj) +{ + obj = obj || this; + var id = GetID(obj); + var ret = CreateArray(Object_Count); + ret[Object_ID] = id; + ret[Object_Origin] = obj; + ret[Object_Status] = GetObjectStatus(obj); + if(GetName(obj) != GetName(0, id)) + { + ret[Object_Name] = GetName(obj); + } + ret[Object_Owner] = GetOwner(obj); + ret[Object_Controller] = GetController(obj); + ret[Object_Killer] = GetKiller(obj); + ret[Object_Category] = GetCategory(obj); + ret[Object_Position] = [GetX(obj), GetY(obj), GetR(obj)]; + ret[Object_Speed] = [GetXDir(obj, 65536), GetYDir(obj, 65536), GetRDir(obj, 65536)]; + ret[Object_Con] = GetCon(obj); + ret[Object_OwnMass] = GetMass(obj) - GetMass(0, id); // maybe save complete Mass instead? + ret[Object_Damage] = GetDamage(obj); + ret[Object_Energy] = GetObjectVal("Energy", 0, obj); + ret[Object_MagicEnergy] = GetMagicEnergy(obj); + ret[Object_Alive] = GetAlive(obj); + ret[Object_Breath] = GetBreath(obj); + ret[Object_ColorDw] = GetColorDw(obj); + ret[Object_Shape] = [GetObjectVal("Offset", 0, obj, 0), GetObjectVal("Offset", 0, obj, 1), GetObjectVal("Width", 0, obj), GetObjectVal("Height", 0, obj)]; + + if(GetObjectVal("OwnVertices", 0, obj)) + { + var vertexNum = GetVertexNum(obj); + var vertices = CreateArray(vertexNum); + for(var i = 0; i < vertexNum; ++i) + { + vertices[i] = [GetVertex(i, VTX_X, obj), GetVertex(i, VTX_Y, obj), GetVertex(i, VTX_CNAT, obj), GetVertex(i, VTX_Friction, obj)]; + } + ret[Object_Vertices] = vertices; + } + + ret[Object_SolidMask] = GetSolidMask(obj); + ret[Object_Picture] = [GetObjectVal("Picture", 0, obj, 0), GetObjectVal("Picture", 0, obj, 1), GetObjectVal("Picture", 0, obj, 2), GetObjectVal("Picture", 0, obj, 3)]; + ret[Object_Entrance] = GetEntrance(obj); + ret[Object_Action] = [GetAction(obj), GetPhase(obj), GetActionTarget(0, obj), GetActionTarget(1, obj), GetObjectVal("ActionData", 0, obj)]; + + var defComponents = [], objComponents = []; + for(var i = 0, componentID; componentID = GetComponent(0, i, 0, id); ++i) + { + var cnt = GetComponent(componentID, 0, 0, id); + if(cnt != 0) + { + defComponents[GetLength(defComponents)] = [componentID, cnt]; + } + } + for(var i = 0, componentID; componentID = GetComponent(0, i, obj); ++i) + { + var cnt = GetComponent(componentID, 0, obj); + if(cnt != 0) + { + objComponents[GetLength(objComponents)] = [componentID, cnt]; + } + } + + var diffComponents = []; + for(var i = 0; i < GetLength(defComponents); ++i) + { + var defID = defComponents[i][0], defCnt = defComponents[i][1]; + var cnt = 0; + for(var j = 0; j < GetLength(objComponents); ++j) + { + if(objComponents[j][0] == defID) + { + cnt = objComponents[j][1]; + ArrayErase(objComponents, j); + break; + } + } + + if(cnt != defCnt) + { + diffComponents[GetLength(diffComponents)] = [defID, cnt]; + } + } + ArrayAppendArray(diffComponents, objComponents); + + if(GetLength(diffComponents) != 0) + { + ret[Object_Components] = diffComponents; + } + + var contents = []; + for(var content in obj->GetContents()) + { + contents[GetLength(contents)] = GetObjectSaveData(content); + } + ret[Object_Contents] = contents; + ret[Object_PlrViewRange] = GetObjectVal("PlrViewRange", 0, obj); + ret[Object_Visibility] = GetVisibility(obj); + ret[Object_BlitMode] = GetObjectBlitMode(obj); + ret[Object_CrewEnabled] = GetCrewEnabled(obj); + ret[Object_ObjectLayer] = GetObjectLayer(obj); + ret[Object_Dir] = GetDir(obj); + ret[Object_ComDir] = GetComDir(obj); + ret[Object_ContactDensity] = GetObjectVal("ContactDensity", 0, obj); + + var locals = []; + for(var f in [0, 1]) + { + var cnt = GetLocalCount(obj, f); + for(var i = 0; i < cnt; ++i) + { + var name = GetLocalByIndex(i, obj, f); + locals[GetLength(locals)] = [name, LocalX(name, obj)]; + } + } + + ret[Object_Locals] = locals; + + var overlays = [[GetGraphics(1, obj, 0), GetGraphics(0, obj, 0), 0, GetGraphics(2, obj, 0), GetGraphics(3, obj, 0), GetGraphics(4, obj, 0), 0, obj->GetObjDrawTransform(0), GetClrModulation(obj, 0)]]; + var offset = 0, diffIndex = 0; + while((offset = obj->GetOverlayValueByIndex(diffIndex, offset)) >= 0) + { + var overlayID = obj->GetOverlayValueByIndex(0, offset, 1); + overlays[GetLength(overlays)] = [obj->GetOverlayValueByIndex(0, offset, 4), obj->GetOverlayValueByIndex(0, offset, 3), overlayID, obj->GetOverlayValueByIndex(0, offset, 2), obj->GetOverlayValueByIndex(0, offset, 5), obj->GetOverlayValueByIndex(0, offset, 6), Object(obj->GetOverlayValueByIndex(0, offset, 8)), obj->GetObjDrawTransform(-1, offset), GetClrModulation(obj, overlayID)]; + diffIndex = 1; + } + ret[Object_Graphics] = overlays; + + var physicals = []; // TODO: Think about StackTemporary? What about Effects? Maybe pop the whole stack while saving and restore afterwards + for(var physical in ["Energy", "Breath", "Walk", "Jump", "Scale", "Hangle", "Dig", "Swim", "Throw", "Push", "Fight", "Magic", "Float", "CanScale", "CanHangle", "CanDig", "CanConstruct", "CanChop", "CanSwimDig", "CanFly", "CorrosionResist", "BreatheWater"]) + { + var value = GetPhysical(physical, PHYS_Current, obj); + if(value != GetPhysical(physical, 0, 0, id)) + { + physicals[GetLength(physicals)] = [physical, value]; + } + } + if(GetLength(physicals) != 0) + { + ret[Object_Physicals] = physicals; + } + + var effects = []; + for(var i = 0, index; index = GetEffect("*", obj, i, 0); ++i) + { + var varCnt = GetEffectVarCount(obj, index); + var effectVars = CreateArray(varCnt); + for(var j = 0; j < varCnt; ++j) + { + effectVars[j] = EffectVar(j, obj, index); + } + effects[i] = [GetEffect(0, obj, index, 1), GetEffect(0, obj, index, 2), GetEffect(0, obj, index, 3), GetEffect(0, obj, index, 4), GetEffect(0, obj, index, 5), GetEffect(0, obj, index, 6), effectVars, index]; + } + if(GetLength(effects) != 0) + { + ret[Object_Effects] = effects; + } + + // TODO: Custom + + return ret; +} + + +global func ApplyObjectSaveData(array data, object obj) +{ + obj = obj || this; + // set values which can trigger callbacks before changing def + obj->SetObjectStatus(data[Object_Status]); + obj->SetCon(data[Object_Con]); + obj->SetOwner(data[Object_Owner]); + obj->DoDamage(data[Object_Damage] - obj->GetDamage()); + if(data[Object_Energy]) + { + if(GetPhysical("Energy", PHYS_Current, obj) < data[Object_Energy]) + { + SetPhysical("Energy", data[Object_Energy], PHYS_Temporary, obj); + } + obj->DoEnergy(data[Object_Energy] - GetObjectVal("Energy", 0, obj), obj, true); + } + + for(var content in data[Object_Contents]) + { + var temp = obj->CreateContents(ROCK); + temp->ApplyObjectSaveData(content); + } + + obj->ChangeDef(data[Object_ID]); + + // the following changes should not call Callbacks anymore + obj->SetName(data[Object_Name]); + obj->SetController(data[Object_Controller]); + obj->SetKiller(data[Object_Killer]); + obj->SetCategory(data[Object_Category]); + obj->SetPosition(data[Object_Position][0], data[Object_Position][1]); + obj->SetR(data[Object_Position][2]); + SetXDir(data[Object_Speed][0], obj, 65536); + SetYDir(data[Object_Speed][1], obj, 65536); + SetRDir(data[Object_Speed][2], obj, 65536); + obj->SetMass(data[Object_OwnMass] - obj->GetMass()); + obj->SetColorDw(data[Object_ColorDw]); + obj->SetShape(data[Object_Shape][0], data[Object_Shape][1], data[Object_Shape][2], data[Object_Shape][3]); + obj->SetSolidMask(data[Object_SolidMask][0], data[Object_SolidMask][1], data[Object_SolidMask][2], data[Object_SolidMask][3], data[Object_SolidMask][4], data[Object_SolidMask][5]); + obj->SetPicture(data[Object_Picture][0], data[Object_Picture][1], data[Object_Picture][2], data[Object_Picture][3]); + obj->SetAlive(data[Object_Alive]); + obj->DoMagicEnergy(data[Object_MagicEnergy] - obj->GetMagicEnergy()); + obj->DoBreath(data[Object_Breath] - obj->GetBreath()); + obj->SetEntrance(data[Object_Entrance]); + + if(data[Object_Vertices]) + { + var cnt = GetLength(data[Object_Vertices]); + while(obj->GetVertexNum() < cnt) + { + obj->AddVertex(); + } + + var i = 0; + for(var vertex in data[Object_Vertices]) + { + obj->SetVertex(i, VTX_X, vertex[0], VTX_SetPermanent); + obj->SetVertex(i, VTX_Y, vertex[1], VTX_SetPermanent); + obj->SetVertex(i, VTX_CNAT, vertex[2], VTX_SetPermanent); + obj->SetVertex(i, VTX_Friction, vertex[3], (i == cnt - 1 && VTX_SetPermanentUpd) || VTX_SetPermanent); + ++i; + } + } + + var id = data[Object_ID]; + for(var physical in ["Energy", "Breath", "Walk", "Jump", "Scale", "Hangle", "Dig", "Swim", "Throw", "Push", "Fight", "Magic", "Float", "CanScale", "CanHangle", "CanDig", "CanConstruct", "CanChop", "CanSwimDig", "CanFly", "CorrosionResist", "BreatheWater"]) + { + obj->SetPhysical(physical, GetPhysical(physical, 0, 0, id), PHYS_Temporary); + } + + if(data[Object_Physicals]) // TODO: Update for StackTemporary and try to represent right mode + { + for(var physical in data[Object_Physicals]) + { + obj->SetPhysical(physical[0], physical[1], PHYS_Temporary); + } + } + + for(var localVar in data[Object_Locals]) + { + LocalX(localVar[0]) = localVar[1]; + } + + if(data[Object_Components]) + { + for(var component in data[Object_Components]) + { + obj->SetComponent(component[0], component[1]); + } + } + SetPlrViewRange(data[Object_PlrViewRange], obj, true); + obj->SetVisibility(data[Object_Visibility]); + obj->SetObjectBlitMode(data[Object_BlitMode]); + obj->SetCrewEnabled(data[Object_CrewEnabled]); + obj->SetObjectLayer(data[Object_ObjectLayer]); + obj->SetContactDensity(data[Object_ContactDensity]); + obj->SetComDir(data[Object_ComDir]); + + // unfortunately there is no SetAction without triggering CallCallbacks + // SetAction at last, so the important stuff is setup already + obj->SetAction(data[Object_Action][0], data[Object_Action][2], data[Object_Action][3], true); + obj->SetPhase(data[Object_Action][1]); + obj->SetActionData(data[Object_Action][4]); + + obj->SetDir(data[Object_Dir]); // Set Dir after Action because Dirs are enabled per action + + for(var graphic in data[Object_Graphics]) + { + SetGraphics(graphic[0], obj, graphic[1], graphic[2], graphic[3], graphic[4], graphic[5], graphic[6]); + + var transform = graphic[7]; + if(GetLength(transform) == 6) + { + SetObjDrawTransform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5], obj, graphic[2]); + } + else + { + SetObjDrawTransform(1000, 0, 0, 0, 1000, 0, obj, graphic[2]); + obj->SetObjDrawTransform2(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5], transform[6], transform[7], transform[8], graphic[2]); + } + + SetClrModulation(graphic[8], obj, graphic[2]); + } + + if(data[Object_Effects]) + { + // WARNING: Can't restore lifetime + for(var effect in data[Object_Effects]) + { + var temp = AddEffect("ApplyEffectDummy", obj, effect[1], effect[2], effect[3], effect[4]); + + for(var i = 0; i < GetLength(effect[6]); ++i) + { + EffectVar(i, obj, temp) = effect[6][i]; + } + + ChangeEffect(0, obj, temp, effect[0], -1); + } + } + + // TODO: Custom +} + +global func InstantiateObjectSaveData(array data) +{ + var ret = CreateObject(ROCK); + ret->ApplyObjectSaveData(data); + return ret; +} |
