summaryrefslogtreecommitdiffstats
path: root/DTObjectSerializing.c
diff options
context:
space:
mode:
Diffstat (limited to 'DTObjectSerializing.c')
-rw-r--r--DTObjectSerializing.c406
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;
+}