diff options
| -rw-r--r-- | DTArrays.c | 52 | ||||
| -rw-r--r-- | DTCallback.c | 324 | ||||
| -rw-r--r-- | DTCallbackScopedVars.c | 55 | ||||
| -rw-r--r-- | DTColorStack.c | 86 | ||||
| -rw-r--r-- | DTCompatibility.c | 105 | ||||
| -rw-r--r-- | DTContents.c | 16 | ||||
| -rw-r--r-- | DTFindObject.c | 338 | ||||
| -rw-r--r-- | DTFormatN.c | 87 | ||||
| -rw-r--r-- | DTMenuCompatibility.c | 20 | ||||
| -rw-r--r-- | DTObjectSerializing.c | 406 | ||||
| -rw-r--r-- | DTParticles.c | 15 | ||||
| -rw-r--r-- | DTPhysicalStack.c | 72 | ||||
| -rw-r--r-- | DTPlayers.c | 82 | ||||
| -rw-r--r-- | DTQuickSort.c | 66 | ||||
| -rw-r--r-- | DTRemoveNotification.c | 43 | ||||
| -rw-r--r-- | DTScenUtils.c | 91 | ||||
| -rw-r--r-- | DTScopedVars.c | 87 | ||||
| -rw-r--r-- | DTTemplateFunctions.c | 307 | ||||
| -rw-r--r-- | DTTimer.c | 26 | ||||
| -rw-r--r-- | DTTransform.c | 240 | ||||
| -rw-r--r-- | DTUtility.c | 744 |
21 files changed, 3262 insertions, 0 deletions
diff --git a/DTArrays.c b/DTArrays.c new file mode 100644 index 0000000..0b78ef4 --- /dev/null +++ b/DTArrays.c @@ -0,0 +1,52 @@ +#strict 2
+
+global func ArrayErase(array& arr, int index)
+{
+ if(index < GetLength(arr))
+ {
+ for(var i = index; i < GetLength(arr) - 1; ++i)
+ {
+ arr[i] = arr[i + 1];
+ }
+ SetLength(arr, GetLength(arr) - 1);
+ }
+}
+
+global func ArrayEraseItem(array& arr, item, bool multiple)
+{
+ var index, count = 0;
+ while((index = GetIndexOf2(item, arr)) != -1)
+ {
+ ArrayErase(arr, index);
+ if(!multiple)
+ {
+ return index;
+ }
+ ++count;
+ }
+ return (!multiple && -1) || count;
+}
+
+global func ArrayInsert(array& arr, int index, value)
+{
+ for(var i = GetLength(arr); i > index; --i)
+ {
+ arr[i] = arr[i - 1];
+ }
+ arr[index] = value;
+}
+
+global func ArrayAppend(array& arr, value)
+{
+ arr[GetLength(arr)] = value;
+}
+
+global func ArrayAppendArray(array& arr, array append)
+{
+ var i = GetLength(arr);
+ SetLength(arr, GetLength(arr) + GetLength(append));
+ for(var val in append)
+ {
+ arr[i++] = val;
+ }
+}
diff --git a/DTCallback.c b/DTCallback.c new file mode 100644 index 0000000..6e026b7 --- /dev/null +++ b/DTCallback.c @@ -0,0 +1,324 @@ +/*-- Extensible callback system --*/ +#strict 2 + +static const CallbackTarget_Bind = -1; +static const CallbackTarget_Global = -2; +static const CallbackTarget_Scenario = -3; + +global func GlobalCallback(string name) { return [CallbackTarget_Global, name]; } +global func ScenarioCallback(string name) { return [CallbackTarget_Scenario, name]; } +global func ObjectCallback(string name, object target) { return [target || this || FatalError("ObjectCallback without target object"), name]; } +global func DefinitionCallback(string name, id target) { return [target || GetID() || FatalError("DefinitionCallback without target definition"), name]; } +global func Callback(string name, target) { return [target || this || GetID() || CallbackTarget_Global, name]; } +global func BindCallback(callback, array binding) { return [CallbackTarget_Bind, callback, binding]; } + +static const BindCallback_Bind_Value = -1; +static const BindCallback_Bind_Context = -2; +static const BindCallback_Bind_ContextDef = -3; +static const BindCallback_Bind_CallbackResult = -4; +static const BindCallback_Bind_ArgumentArrayPart = -5; +static const BindCallback_Bind_Reference = -6; +global func Bind(value) { return [BindCallback_Bind_Value, value]; } +global func Bind_Context() { return [BindCallback_Bind_Context]; } +global func Bind_ContextDef() { return [BindCallback_Bind_ContextDef]; } +global func Bind_CallbackResult(callback) { return [BindCallback_Bind_CallbackResult, callback]; } +global func Bind_ArgumentArrayPart(int argument, part) +{ + if(GetType(part) != C4V_Array) + { + part = [part]; + } + return [BindCallback_Bind_ArgumentArrayPart, argument, part]; +} +global func Bind_Reference(array scopedVar) { return [BindCallback_Bind_Reference, scopedVar]; } + +global func Call(callback) +{ + if(GetType(callback) == C4V_String) + { + return _inherited(callback, ...); + } + else + { + return CallA(callback, CreateFilledArray(...)); + } +} + +global func CallA(callback, args, bool safe, array refs) +{ + if(GetType(callback) == C4V_String) + { + callback = [this, callback]; + } + if(GetType(callback) != C4V_Array) + { + return _inherited(callback, args, ...); + } + else + { + refs = refs || []; + var safeModifier = ""; + if(safe) + { + safeModifier = "~"; + } + var target = callback[0], function = callback[1]; + var argsStr = "", pos = 0; + for(var arg in args) + { + if(pos > 0) + { + argsStr = Format("%s, ", argsStr); + } + if(refs[pos]) + { + argsStr = Format("%sScopedVar(%s)", argsStr, Serialize(arg)); + } + else + { + argsStr = Format("%s%s", argsStr, Serialize(arg)); + } + ++pos; + } + if(target == CallbackTarget_Global) + { + return GlobalEval(Format("%s(%s)", function, argsStr)); + } + else if(target == CallbackTarget_Scenario) + { + return GameCall(function, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + } + else if(target == CallbackTarget_Bind) + { + return CallA(callback[1], BindArgs(callback[2], args, safe, refs), safe, refs); + } + else + { + if(GetType(target) == C4V_C4Object || GetType(target) == C4V_C4ID) + { + return eval(Format("%s->%s%s(%s)", Serialize(target), safeModifier, function, argsStr)); + } + else + { + return (this && this->~CallCustom(callback, args, ...)) || ROCK->~CallCustom(callback, args, ...); + } + } + } +} + +global func BindArgs_ArgumentArrayPart(array binding, array args, bool safe) +{ + var ret = args[binding[0]]; + for(var i = 1; i < GetLength(binding); ++i) + { + if(!safe || GetType(ret) == C4V_Array) + { + ret = ret[binding[i]]; + } + else + { + return 0; + } + } + return ret; +} + +global func BindCustomArgs() { return _inherited(...); } // this allows "overloading" this function even if the "overloading" function is loaded before + +global func BindArgs(array binding, array args, bool safe, array& refs) +{ + refs = []; + var ret = CreateArray(GetLength(binding)), pos = 0; + for(var bind in binding) + { + if(GetType(bind) == C4V_Int || GetType(bind) == C4V_Any && bind >= 0) + { + ret[pos] = args[bind]; + } + else if(GetType(bind) == C4V_Array && GetLength(bind)) + { + if(bind[0] == BindCallback_Bind_Value) + { + ret[pos] = bind[1]; + } + else if(bind[0] == BindCallback_Bind_Context) + { + ret[pos] = this; + } + else if(bind[0] == BindCallback_Bind_ContextDef) + { + ret[pos] = GetID(); + } + else if(bind[0] == BindCallback_Bind_CallbackResult) + { + ret[pos] = CallA(bind[1], args, safe); + } + else if(bind[0] == BindCallback_Bind_ArgumentArrayPart) + { + ret[pos] = BindArgs_ArgumentArrayPart(bind[2], args[bind[1]], safe); + } + else if(bind[0] == BindCallback_Bind_Reference) + { + refs[pos] = true; + ret[pos] = bind[1]; + } + else if(GetType(bind[0]) == C4V_Int && bind[0] < 0) + { + ret[pos] = BindCustomArgs(bind, args, safe); + } + else + { + ret[pos] = BindArgs(bind, args, safe); + } + } + else + { + FatalError(Format("BindArgs: incorrect binding %v", bind)); + } + ++pos; + } + return ret; +} + +global func GlobalEval(string code) +{ + var effect = AddEffect("IntGlobalEval", 0, 1); + var ret = EffectCall(0, effect, "Eval", code); + RemoveEffect(0, 0, effect); + return ret; +} + +global func FxIntGlobalEvalEval(object target, int effectNumber, string code) +{ + return eval(code); +} + +global func foreach(array arr, callback) +{ + var i = 0; + for(var val in arr) + { + CallA(callback, [val, i++]); + } +} + +global func CheckCallback(callback) +{ + if(GetType(callback) == C4V_String) + { + return true; + } + + if(GetType(callback) == C4V_Array) + { + if(GetType(callback[0]) == C4V_Int) + { + if(callback[0] == CallbackTarget_Bind && GetLength(callback) == 3) + { + if(CheckCallback(callback[1]) && CheckBindCallbackBinding(callback[2])) + { + return true; + } + } + else if(callback[0] == CallbackTarget_Global || callback[0] == CallbackTarget_Scenario) + { + if(GetLength(callback) == 2 && GetType(callback[1]) == C4V_String && callback[1] != "") + { + return true; + } + } + } + else if(GetType(callback[0]) == C4V_C4ID || GetType(callback[0]) == C4V_C4Object) + { + if(GetLength(callback) == 2 && GetType(callback[1]) == C4V_String && callback[1] != "") + { + return true; + } + } + } + + return (this && this->~CheckCustomCallback(callback, ...)) || ROCK->~CheckCustomCallback(callback, ...); +} + +global func CheckBindCallbackBinding(array binding) +{ + for(var b in binding) + { + if(b && GetType(b) != C4V_Int) + { + if(GetType(b) == C4V_Array) + { + if(b[0] == BindCallback_Bind_Value) + { + if(GetLength(b) != 2) + { + return false; + } + } + else if(b[0] == BindCallback_Bind_Context || b[0] == BindCallback_Bind_ContextDef) + { + continue; + } + else if(b[0] == BindCallback_Bind_CallbackResult) + { + if(GetLength(b) != 2 || !CheckCallback(b[1])) + { + return false; + } + } + else if(b[0] == BindCallback_Bind_ArgumentArrayPart) + { + if(GetLength(b) != 3) + { + return false; + } + + if(b[1] && (GetType(b[1]) != C4V_Int || b[1] < 0)) + { + return false; + } + + for(var part in b[2]) + { + if(part && (GetType(part) != C4V_Int || part < 0)) + { + return false; + } + } + } + else if(b[0] == BindCallback_Bind_Reference) + { + if(GetLength(b) != 2 || !CheckScopedVar(b[1])) + { + return false; + } + } + else if(GetType(b[0]) == C4V_Int && b[0] < 0) + { + if(!CheckBindCallbackCustomBinding(b)) + { + return false; + } + } + else + { + if(!CheckBindCallbackBinding(b)) + { + return false; + } + } + } + else + { + return false; + } + } + else if(b < 0) + { + return false; + } + } + return true; +} + +global func CheckBindCallbackCustomBinding() { return _inherited(...); } diff --git a/DTCallbackScopedVars.c b/DTCallbackScopedVars.c new file mode 100644 index 0000000..75eb5e2 --- /dev/null +++ b/DTCallbackScopedVars.c @@ -0,0 +1,55 @@ +#strict 2 + +static const ScopedVar_Callback = 4; + +global func CallbackVar(callback) { return [ScopedVar_Callback, callback]; } + +global func &CustomScopedVar(array variable) +{ + if(variable[0] == ScopedVar_Callback) + { + return CallA(variable[1], []); + } + else + { + return _inherited(variable, ...); + } +} + +static const BindCallback_Bind_ScopedVar = -6; + +global func Bind_Var(array scopedVar) { return [BindCallback_Bind_ScopedVar, scopedVar]; } + +global func BindCustomArgs(array bind, array args, bool safe) +{ + if(bind[0] == BindCallback_Bind_ScopedVar) + { + return ScopedVar(bind[1]); + } + else + { + return _inherited(bind, args, safe, ...); + } +} + +global func CheckCustomScopedVar(array variable) +{ + if(GetType(variable) == C4V_Array && variable[0] == ScopedVar_Callback && GetLength(variable) == 2) + { + if(CheckCallback(variable[1])) + { + return true; + } + } + + return _inherited(variable, ...); +} + +global func CheckBindCallbackCustomBinding(binding) +{ + if(GetType(binding) == C4V_Array && GetLength(binding) == 2 && binding[0] == BindCallback_Bind_ScopedVar && CheckScopedVar(binding[1])) + { + return true; + } + return _inherited(binding, ...); +} diff --git a/DTColorStack.c b/DTColorStack.c new file mode 100644 index 0000000..9f9535f --- /dev/null +++ b/DTColorStack.c @@ -0,0 +1,86 @@ +#strict 2
+
+global func GetClrModulationStack(object target)
+{
+ target || FatalError("GetClrModulationStack: no target object given");
+ return GetEffect("ClrModulationStack", target) || AddEffect("ClrModulationStack", target, 200);
+}
+
+global func AddClrModulation(int color, int baseColor, int factor, int precision, object target)
+{
+ baseColor = baseColor || RGB(127, 127, 127);
+ target = target || this || FatalError("AddClrModulation: no target object given");
+ factor = factor || 1;
+ precision = precision || 1;
+
+ return EffectCall(target, GetClrModulationStack(target), "AddModulation", color, baseColor, factor, precision);
+}
+
+global func RemoveClrModulation(int id, object target)
+{
+ target = target || this || FatalError("RemoveClrModulation: no target object given");
+
+ return EffectCall(target, GetClrModulationStack(target), "RemoveModulation", id);
+}
+
+global func FxClrModulationStackStart(object target, int effectNumber, int temp)
+{
+ if(!temp)
+ {
+ EffectVar(1, target, effectNumber) = [];
+ }
+}
+
+global func FxClrModulationStackAddModulation(object target, int effectNumber, int color, int baseColor, int factor, int precision)
+{
+ ArrayAppend(EffectVar(1, target, effectNumber), [++EffectVar(0, target, effectNumber), color, baseColor, factor, precision]);
+ EffectCall(target, effectNumber, "ApplyModulation");
+ return EffectVar(0, target, effectNumber);
+}
+
+global func FxClrModulationStackRemoveModulation(object target, int effectNumber, int id)
+{
+ for(var i = 0; i < GetLength(EffectVar(1, target, effectNumber)); ++i)
+ {
+ if(EffectVar(1, target, effectNumber)[i][0] == id)
+ {
+ ArrayErase(EffectVar(1, target, effectNumber), i);
+ EffectCall(target, effectNumber, "ApplyModulation");
+ return true;
+ }
+ }
+ return 0;
+}
+
+global func FxClrModulationStackApplyModulation(object target, int effectNumber)
+{
+ if(GetLength(EffectVar(1, target, effectNumber)) == 0)
+ {
+ SetClrModulation(0, target);
+ return 0;
+ }
+ var r, g, b, a;
+ SplitRGBaValue(EffectVar(1, target, effectNumber)[0][1], r, g, b, a);
+ a = 255 - a;
+ for(var i = 1; i < GetLength(EffectVar(1, target, effectNumber)); ++i)
+ {
+ var clrPart = EffectVar(1, target, effectNumber)[i];
+ var mr, mg, mb, ma, br, bg, bb, ba;
+ SplitRGBaValue(clrPart[1], mr, mg, mb, ma);
+ SplitRGBaValue(clrPart[2], br, bg, bb, ba);
+ ma = 255 - ma;
+ a *= ma;
+ a /= 0xFF;
+ r += mr - br;
+ r *= clrPart[3];
+ r /= clrPart[4];
+ g += mg - bg;
+ g *= clrPart[3];
+ g /= clrPart[4];
+ b += mb - bb;
+ b *= clrPart[3];
+ b /= clrPart[4];
+ }
+ SetClrModulation(RGBa(BoundBy(r, 0, 255), BoundBy(g, 0, 255), BoundBy(b, 0, 255), 255 - a), target);
+ return true;
+}
diff --git a/DTCompatibility.c b/DTCompatibility.c new file mode 100644 index 0000000..d3ae922 --- /dev/null +++ b/DTCompatibility.c @@ -0,0 +1,105 @@ +/*-- Avoid errors from non-existing Engine-Functions --*/
+
+#strict 2
+
+static hostFeatures;
+static hostTime;
+
+global func SetGameComment() { return _inherited(...); }
+global func IsHost() { return _inherited(...); }
+global func RequestHostFeature(string feature) { if(!HaveHostFeature(feature) || feature == "HostTime") return _inherited(feature, ...); }
+
+global func AnnounceHostFeature(string feature)
+{
+ hostFeatures || (hostFeatures = []);
+ hostFeatures[GetLength(hostFeatures)] = feature;
+}
+
+global func HaveHostFeature(string feature)
+{
+ hostFeatures || (hostFeatures = []);
+ return GetIndexOf(feature, hostFeatures) != -1;
+}
+
+global func ReRequestHostFeatures()
+{
+ if(IsNetwork())
+ {
+ var features = hostFeatures;
+ hostFeatures = [];
+
+ if(features)
+ {
+ for(var feature in features)
+ {
+ RequestHostFeature(feature);
+ }
+ }
+ }
+}
+
+global func AnnounceHostTime(int time)
+{
+ hostTime = time;
+}
+
+global func GetSystemTime(int what)
+{
+ if(HaveHostFeature("HostTime"))
+ {
+ if(what == 10) // is leap year
+ {
+ var year = GetSystemTime(0);
+ return !!((!(year % 4) && year % 100) || !(year % 400));
+ }
+ if(what == 9) return hostTime; // timestamp
+ if(what == 8) // day of year
+ {
+ return (hostTime - (GetSystemTime(0) - 1970) * 31556926)/(3600*24) + 1;
+ }
+ if(what == 7) return 0;
+ if(what == 6) return hostTime % 60;
+ if(what == 5) return (hostTime/60) % 60;
+ if(what == 4) return (hostTime/3600) % 24;
+ if(what == 3)
+ {
+ var dayofyear = GetSystemTime(8);
+ var leapyear = GetSystemTime(10);
+ if(dayofyear < 32) return dayofyear;
+ else if(dayofyear < 60 + leapyear) return dayofyear - 31;
+ else if(dayofyear < 91 + leapyear) return dayofyear - 59;
+ else if(dayofyear < 121 + leapyear) return dayofyear - (90 + leapyear);
+ else if(dayofyear < 152 + leapyear) return dayofyear - (120 + leapyear);
+ else if(dayofyear < 182 + leapyear) return dayofyear - (151 + leapyear);
+ else if(dayofyear < 213 + leapyear) return dayofyear - (181 + leapyear);
+ else if(dayofyear < 244 + leapyear) return dayofyear - (212 + leapyear);
+ else if(dayofyear < 274 + leapyear) return dayofyear - (243 + leapyear);
+ else if(dayofyear < 305 + leapyear) return dayofyear - (273 + leapyear);
+ else if(dayofyear < 335 + leapyear) return dayofyear - (204 + leapyear);
+ else return dayofyear - (334 + leapyear);
+ }
+ if(what == 2)
+ {
+ return ((hostTime/86400) + 4) % 7;
+ }
+ if(what == 1)
+ {
+ var dayofyear = GetSystemTime(8);
+ var leapyear = GetSystemTime(10);
+ if(dayofyear < 32) return 1;
+ else if(dayofyear < 60 + leapyear) return 2;
+ else if(dayofyear < 91 + leapyear) return 3;
+ else if(dayofyear < 121 + leapyear) return 4;
+ else if(dayofyear < 152 + leapyear) return 5;
+ else if(dayofyear < 182 + leapyear) return 6;
+ else if(dayofyear < 213 + leapyear) return 7;
+ else if(dayofyear < 244 + leapyear) return 8;
+ else if(dayofyear < 274 + leapyear) return 9;
+ else if(dayofyear < 305 + leapyear) return 10;
+ else if(dayofyear < 335 + leapyear) return 11;
+ else return 12;
+ }
+ if(what == 0) return 1970 + ((hostTime + 31556926 * 2)/(31556926)) - 2;
+ }
+ else return _inherited(what, ...);
+}
diff --git a/DTContents.c b/DTContents.c new file mode 100644 index 0000000..cb49691 --- /dev/null +++ b/DTContents.c @@ -0,0 +1,16 @@ +#strict 2 + +global func GetContents(bool recursive, object obj) +{ + obj = obj || this; + var ret = []; + for(var i = 0; i < obj->ContentsCount(); ++i) + { + ret[GetLength(ret)] = obj->Contents(i); + if(recursive) + { + ArrayAppendArray(ret, obj->Contents(i)->GetContents(true)); + } + } + return ret; +} diff --git a/DTFindObject.c b/DTFindObject.c new file mode 100644 index 0000000..b7205e6 --- /dev/null +++ b/DTFindObject.c @@ -0,0 +1,338 @@ +/*-- + * Overloads Find_-functions available in System.c4g so Find_Or and Find_And can be used inside other criterions like so: + * Find_ID(Find_Or(ROCK, FLNT)) + * Find_Func("IsBlock", ["CompareLayer", LAYER_FG]) + * --*/ +#strict 2 + +global func ProxySimpleFind_AndOr(int type, criteria) +{ + if(GetType(criteria) != C4V_Array) + { + return [type, criteria]; + } + else + { + var ret = [criteria[0]]; + for(var i = 1; i < GetLength(criteria); ++i) + { + ret[i] = [type, criteria[i]]; + } + return ret; + } +} + +global func ProxyFind_AndOr(criteria, &type, &parts) +{ + type = criteria[0]; + parts = CreateArray(GetLength(criteria) - 1); + for(var i = 1; i < GetLength(criteria); ++i) + { + if(GetType(criteria[i]) == C4V_Array) + { + parts[i - 1] = criteria[i]; + } + else + { + parts[i - 1] = [criteria[i]]; + } + } +} + +global func Find_Action(what) { return ProxySimpleFind_AndOr(C4FO_Action, what); } +global func Find_Category(what) { return ProxySimpleFind_AndOr(C4FO_Category, what); } +global func Find_Container(what) { return ProxySimpleFind_AndOr(C4FO_Container, what); } +global func Find_Controller(what) { return ProxySimpleFind_AndOr(C4FO_Controller, what); } +global func Find_ID(what) { return ProxySimpleFind_AndOr(C4FO_ID, what); } +global func Find_Layer(what) { return ProxySimpleFind_AndOr(C4FO_Layer, what); } +global func Find_OCF(what) { return ProxySimpleFind_AndOr(C4FO_OCF, what); } +global func Find_Owner(what) { return ProxySimpleFind_AndOr(C4FO_Owner, what); } + +global func Find_Exclude(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_InRect(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_AtRect(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_OnLine(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Distance(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_ActionTarget(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Hostile(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Allied(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Func(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_PathFree(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Command(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_ColorDw(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Effect(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Local(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_Team(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_FuncEqual(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_FuncInside(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + +global func Find_ID(what) +{ + if(GetType(what) != C4V_Array) + { + return _inherited(what); + } + + var ret = [], parts, i = 0; + ProxyFind_AndOr(what, ret[0], parts); + for(var part in parts) + { + ret[++i] = _inherited(part[0], part[1], part[2], part[3], part[4], part[5], part[6], part[7], part[8], part[9]); + } + return ret; +} + diff --git a/DTFormatN.c b/DTFormatN.c new file mode 100644 index 0000000..0f9481b --- /dev/null +++ b/DTFormatN.c @@ -0,0 +1,87 @@ +#strict 2
+
+global func FormatN(string format, array placeholders, array items)
+{
+ if(!items && GetType(placeholders[0]) == C4V_Array)
+ {
+ items = CreateArray(GetLength(placeholders));
+ for(var i = 0; i < GetLength(placeholders); ++i)
+ {
+ items[i] = placeholders[i][1];
+ placeholders[i] = placeholders[i][0];
+ }
+ }
+
+ var ret = "";
+
+ var inPlaceholder = 0;
+ var placeholderType = "";
+ var placeholderPart = "";
+
+ for(var i = 0; i < GetLength(format); ++i)
+ {
+ var c = GetChar(format, i);
+ if(c == 37) // %
+ {
+ if(inPlaceholder == 0)
+ {
+ inPlaceholder = 1;
+ }
+ else if(inPlaceholder == 1)
+ {
+ if(c == 37 && GetLength(placeholderType) == 0) // %
+ {
+ ret = Format("%s%%", ret);
+ inPlaceholder = 0;
+ }
+ else
+ {
+ inPlaceholder = 2;
+ }
+ }
+ else if(inPlaceholder == 2)
+ {
+ var index = GetIndexOf2(placeholderPart, placeholders);
+ if(index == -1)
+ {
+ FatalError(Format("FormatN: Unkown placeholder \"%s\"", placeholderPart));
+ return 0;
+ }
+
+ ret = Format(Format("%%s%%%s", placeholderType), ret, items[index]);
+
+ inPlaceholder = 0;
+ placeholderType = "";
+ placeholderPart = "";
+ }
+ }
+ else
+ {
+ if(inPlaceholder == 0)
+ {
+ ret = Format("%s%c", ret, c);
+ }
+ else if(inPlaceholder == 1)
+ {
+ placeholderType = Format("%s%c", placeholderType, c);
+ }
+ else if(inPlaceholder == 2)
+ {
+ placeholderPart = Format("%s%c", placeholderPart, c);
+ }
+ }
+ }
+
+ if(inPlaceholder == 1)
+ {
+ FatalError(Format("FormatN: Placeholder not finished at end of format-string: \"%%%s\"", placeholderType));
+ return 0;
+ }
+ else if(inPlaceholder == 2)
+ {
+ FatalError(Format("FormatN: Placeholder not finished at end of format-string: \"%%%s%%%s\"", placeholderType, placeholderPart));
+ return 0;
+ }
+
+ return ret;
+}
diff --git a/DTMenuCompatibility.c b/DTMenuCompatibility.c new file mode 100644 index 0000000..0401b95 --- /dev/null +++ b/DTMenuCompatibility.c @@ -0,0 +1,20 @@ +#strict 2 +#appendto MN7I + +static const Menu_Enum_Symbol = Menu_Layout_Symbol; +static const Menu_Enum_InfoCaption = Menu_Layout_InfoCaption; + +static const Menu_Enum_Caption = Menu_Layout_Caption; +static const Menu_Enum_Value = Menu_Layout_Value; + +global func Menu_SubMenu(caption, symbol, string infoCaption, array menuEntries_Settings, int count, int extra, XPar1, XPar2) +{ + if(GetType(caption) == C4V_Array) // caption contains all entry settings for the current menu and symbol contains all submenu entries and settings + { + return inherited(caption, symbol, infoCaption, menuEntries_Settings, count, extra, XPar1, XPar2, ...); + } + else + { + return inherited([Menu_Entry_Caption(caption), Menu_Entry_Symbol(symbol), Menu_Entry_Count(count), Menu_Entry_InfoCaption(infoCaption), Menu_Entry_Extra(extra), Menu_Entry_XPar1(XPar1), Menu_Entry_XPar2(XPar2)], menuEntries_Settings); + } +} 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; +} diff --git a/DTParticles.c b/DTParticles.c new file mode 100644 index 0000000..5373134 --- /dev/null +++ b/DTParticles.c @@ -0,0 +1,15 @@ +#strict 2 + +global func DrawParticleRect(string name, array rect, int dist, int a, b, int yDir) +{ + var ret = 0; + if(GetType(b) != C4V_Array) + { + b = [b, b, b, b]; + } + ret = DrawParticleLine(name, rect[0], rect[1], rect[0] + rect[2], rect[1], dist, a, b[0], b[1], yDir); + ret += DrawParticleLine(name, rect[0] + rect[2], rect[1], rect[0] + rect[2], rect[1] + rect[3], dist, a, b[1], b[2], yDir); + ret += DrawParticleLine(name, rect[0] + rect[2], rect[1] + rect[3], rect[0], rect[1] + rect[3], dist, a, b[2], b[3], yDir); + ret += DrawParticleLine(name, rect[0], rect[1] + rect[3], rect[0], rect[1], dist, a, b[3], b[0], yDir); + return ret; +} diff --git a/DTPhysicalStack.c b/DTPhysicalStack.c new file mode 100644 index 0000000..c0aa7ad --- /dev/null +++ b/DTPhysicalStack.c @@ -0,0 +1,72 @@ +#strict 2
+
+global func GetPhysicalFactorStack(object target)
+{
+ target || FatalError("GetPhysicalFactorStack: no target object given");
+ return GetEffect("PhysicalFactorStack", target) || AddEffect("PhysicalFactorStack", target, 200);
+}
+
+global func AddPhysicalFactor(string physical, int factor, int precision, object target)
+{
+ target = target || this || FatalError("AddPhysicalFactor: no target object given");
+ precision = precision || 100;
+
+ return EffectCall(target, GetPhysicalFactorStack(target), "AddFactor", physical, factor, precision);
+}
+
+global func RemovePhysicalFactor(int id, object target)
+{
+ target = target || this || FatalError("AddPhysicalFactor: no target object given");
+
+ return EffectCall(target, GetPhysicalFactorStack(target), "RemoveFactor", id);
+}
+
+global func FxPhysicalFactorStackStart(object target, int effectNumber, int temp)
+{
+ if(!temp)
+ {
+ EffectVar(1, target, effectNumber) = [];
+ }
+}
+
+global func FxPhysicalFactorStackAddFactor(object target, int effectNumber, string physical, int factor, int precision)
+{
+ ArrayAppend(EffectVar(1, target, effectNumber), [++EffectVar(0, target, effectNumber), physical, factor, precision]);
+ EffectCall(target, effectNumber, "ApplyPhysical", physical);
+ return EffectVar(0, target, effectNumber);
+}
+
+global func FxPhysicalFactorStackRemoveFactor(object target, int effectNumber, int id)
+{
+ for(var i = 0; i < GetLength(EffectVar(1, target, effectNumber)); ++i)
+ {
+ if(EffectVar(1, target, effectNumber)[i][0] == id)
+ {
+ var physical = EffectVar(1, target, effectNumber)[i][1];
+ ArrayErase(EffectVar(1, target, effectNumber), i);
+ EffectCall(target, effectNumber, "ApplyPhysical", physical);
+ return true;
+ }
+ }
+ return 0;
+}
+
+global func FxPhysicalFactorStackApplyPhysical(object target, int effectNumber, string physical)
+{
+ var phys = GetPhysical(physical, PHYS_Temporary, target);
+ if(phys)
+ {
+ ResetPhysical(target, physical);
+ }
+ phys = GetPhysical(physical, PHYS_Current, target);
+ for(var factor in EffectVar(1, target, effectNumber))
+ {
+ if(factor[1] == physical)
+ {
+ phys *= factor[2];
+ phys /= factor[3];
+ }
+ }
+ SetPhysical(physical, phys, PHYS_StackTemporary, target);
+ return phys;
+}
diff --git a/DTPlayers.c b/DTPlayers.c new file mode 100644 index 0000000..ab75aef --- /dev/null +++ b/DTPlayers.c @@ -0,0 +1,82 @@ +/*-- Helper functions for iterating through all players and teams --*/ +#strict 2 + +static const Player_Number = 0; +static const Player_ID = 0 + 1; +static const Player_Name = 0 + 1 + 1; +static const Player_TaggedName = 0 + 1 + 1 + 1; +static const Player_Color = 0 + 1 + 1 + 1 + 1; +static const Player_Team = 0 + 1 + 1 + 1 + 1 + 1; +static const Player_Type = 0 + 1 + 1 + 1 + 1 + 1 + 1; + +global func GetPlayers(int team, bool exclude) +{ + var ret = []; + for(var plr, plrTeam, i = 0; (i < GetPlayerCount()) && ((plrTeam = GetPlayerTeam(plr = GetPlayerByIndex(i))) || true); ++i) + { + if(!team || (team == plrTeam) != exclude) + { + var plrInfo = []; + plrInfo[Player_Number] = plr; + plrInfo[Player_ID] = GetPlayerID(plr); + plrInfo[Player_Name] = GetPlayerName(plr); + plrInfo[Player_TaggedName] = GetTaggedPlayerName(plr); + plrInfo[Player_Color] = GetPlrColorDw(plr); + plrInfo[Player_Team] = GetPlayerTeam(plr); + plrInfo[Player_Type] = GetPlayerType(plr); + ret[GetLength(ret)] = plrInfo; + } + } + + return ret; +} + +global func GetPlayerNumbers(int team, bool exclude) +{ + var ret = []; + for(var plr, i = 0; (i < GetPlayerCount()) && ((plr = GetPlayerByIndex(i)) || true); ++i) + { + if(!team || (team == GetPlayerTeam(plr)) != exclude) + { + ret[GetLength(ret)] = plr; + } + } + return ret; +} + +global func GetTaggedTeamName(int team) +{ + return Format("<c %x>%s</c>", GetTeamColor(team), GetTeamName(team)); +} + +static const Team_ID = 0; +static const Team_Name = 0 + 1; +static const Team_TaggedName = 0 + 1 + 1; +static const Team_Color = 0 + 1 + 1 + 1; +static const Team_Players = 0 + 1 + 1 + 1 + 1; + +global func GetTeams() +{ + var ret = []; + for(var team, i = 0; (i < GetTeamCount()) && ((team = GetTeamByIndex(i)) || true); ++i) + { + var teamInfo = []; + teamInfo[Team_ID] = team; + teamInfo[Team_Name] = GetTeamName(team); + teamInfo[Team_TaggedName] = GetTaggedTeamName(); + teamInfo[Team_Color] = GetTeamColor(team); + teamInfo[Team_Players] = GetPlayers(team); + ret[GetLength(ret)] = teamInfo; + } + return ret; +} + +global func GetTeamIDs() +{ + var ret = []; + for(var team, i = 0; (i < GetTeamCount()) && ((team = GetTeamByIndex(i)) || true); ++i) + { + ret[GetLength(ret)] = team;; + } + return ret; +} diff --git a/DTQuickSort.c b/DTQuickSort.c new file mode 100644 index 0000000..7434263 --- /dev/null +++ b/DTQuickSort.c @@ -0,0 +1,66 @@ +#strict 2 + +global func SortNumeric(int a, int b) +{ + if(a < b) + { + return -1; + } + else if(a > b) + { + return 1; + } +} + +global func SortNumericInverse(int a, int b) +{ + return -SortNumeric(a, b); +} + +global func QSort(array& data, callback) // WARNING: Can cause stack-overflow with too much data +{ + if(callback == true) + { + callback = GlobalCallback("SortNumericInverse"); + } + QSort_Part(data, callback || GlobalCallback("SortNumeric"), 0, GetLength(data) - 1); + return data; +} + +global func QSort_Part(array& data, callback, int left, int right) +{ + if(left < right) + { + // Partitioning + var pPos = RandomX(left, right); + var p = data[pPos]; + var tmp; + + tmp = data[pPos]; + data[pPos] = data[right]; + data[right] = tmp; + pPos = right; + + var i = left - 1; + for(var j = left; j <= right; ++j) + { + if(Call(callback, data[j], p) < 0) + { + ++i; + tmp = data[i]; + data[i] = data[j]; + data[j] = tmp; + } + } + + ++i; + + tmp = data[i]; + data[i] = data[pPos]; + data[pPos] = tmp; + // ----- + + QSort_Part(data, callback, left, i - 1); + QSort_Part(data, callback, i + 1, right); + } +} diff --git a/DTRemoveNotification.c b/DTRemoveNotification.c new file mode 100644 index 0000000..eb4a47c --- /dev/null +++ b/DTRemoveNotification.c @@ -0,0 +1,43 @@ +#strict 2
+
+global func AddRemoveNotification(callback, object target, object callbackTarget, int prio)
+{
+ if(!target || !callback)
+ {
+ return;
+ }
+ callbackTarget = callbackTarget || this;
+ return AddEffect("IntRemoveNotifier", target, prio || 1, 0, callbackTarget, 0, callback);
+}
+
+global func RemoveRemoveNotification(int id, object target)
+{
+ if(!target)
+ {
+ return;
+ }
+ return RemoveEffect(0, target, id);
+}
+
+global func FxIntRemoveNotifierStart(object target, int effectNumber, int temp, callback)
+{
+ if(!temp)
+ {
+ EffectVar(0, target, effectNumber) = callback;
+ }
+}
+
+global func FxIntRemoveNotifierStop(object target, int effectNumber, int reason, bool temp)
+{
+ if(!temp)
+ {
+ if(reason == FX_Call_RemoveClear)
+ {
+ Call(EffectVar(0, target, effectNumber), target);
+ }
+ else if(reason == FX_Call_RemoveDeath)
+ {
+ return FX_Stop_Deny;
+ }
+ }
+}
diff --git a/DTScenUtils.c b/DTScenUtils.c new file mode 100644 index 0000000..be55cfe --- /dev/null +++ b/DTScenUtils.c @@ -0,0 +1,91 @@ +#strict 2
+
+static const ObjStr_Skip = -1;
+static const ObjStr_Defaults = 0;
+static const ObjStr_NoDefault = 1;
+static const ObjStr_NoLocals = 2;
+static const ObjStr_NoContents = 4;
+static const ObjStr_ModeParts = 1; // NoDefault
+
+global func LogObjects(array criteria, bool inline, bool& first)
+{
+ for(var obj in FindObjects(criteria))
+ {
+ var str = GetObjectString(obj);
+ if(str) Log((inline && ((first && " %s") || ", %s")) || " %s;", str);
+ first = false;
+ }
+}
+
+global func GetObjects(bool inline)
+{
+ var first = true, exp = Find_And(Find_Not(Find_Func("IsHUD")), Find_Not(Find_Func("IsLight")), Find_NoContainer());
+ if(inline) Log("[");
+ LogObjects(Find_And(Find_Category(C4D_Rule | C4D_Goal | C4D_Environment), exp), inline, first); // goals, rules and environment first
+ LogObjects(Find_And(Find_Not(Find_Category(C4D_Rule | C4D_Goal | C4D_Environment)), exp), inline, first); // and the rest
+ if(inline) Log("]");
+}
+
+global func GetObjectString(obj)
+{
+ var extra, extray, custom, customStr = "";
+ extra = "";
+ extray = 0;
+ custom = obj->~CustomObjectString(customStr);
+ if(custom == ObjStr_Skip)
+ {
+ return;
+ }
+ else if((custom & ObjStr_ModeParts) != ObjStr_NoDefault)
+ {
+ if(obj->GetR() != 0) extra = Format("%s->SetRX(%d)", extra, obj->GetR());
+ if(obj->GetCon() != 100)
+ {
+ extra = Format("%s->SetConX(%d)", extra, obj->GetCon());
+ extray = -GetDefCoreVal("Offset", "DefCore", GetID(obj), 1) * (100-obj->GetCon()) / 100;
+ }
+ if(obj->GetDir())
+ {
+ extra = Format("%s->SetDirX(%d)", extra, obj->GetDir());
+ }
+ if(!(custom & ObjStr_NoLocals)) for(var iFunc = 0; iFunc < 2; ++iFunc)
+ {
+ for(var i = 0; i < GetLocalCount(obj, iFunc); ++i)
+ {
+ var key = GetLocalByIndex(i, obj, iFunc);
+ var val;
+ if(GetType(key) == C4V_Int || GetType(key) == C4V_Any) val = Local(key, obj);
+ else if(GetType(key) == C4V_String) val = LocalN(key, obj);
+ if(val == 0) continue;
+ extra = Format("%s->SetLocalX(%s, %s)", extra, Serialize(key), Serialize(val));
+ }
+ }
+ if(!(custom & ObjStr_NoContents)) for(var content in FindObjects(Find_Container(obj)))
+ {
+ extra = Format("%s->EnterX(%s)", extra, GetObjectString(content));
+ }
+ }
+ if(GetCategory(obj) & C4D_StaticBack)
+ {
+ extray -= GetDefOffset(GetID(obj), 1) * 2 + GetDefHeight(GetID(obj));
+ }
+ return Format("CreateObjectX(%i, %d, %d, %d)%s%s",
+ GetID(obj),
+ GetX(obj),
+ GetY(obj)/* - GetDefCoreVal("Offset", "DefCore", GetID(obj), 1) - extray*/,
+ GetOwner(obj),
+ extra, customStr);
+}
+
+global func CreateObjectX(id id, int x, int y, int owner) { return CreateObject(id, x, y, owner)->SetPositionX(x, y); }
+global func SetPositionX(int x, int y) { this->SetPosition(x, y); return this; }
+global func SetDirX(int dir) { this->SetDir(dir); return this; }
+global func SetRX(int r) { this->SetR(r); return this; }
+global func SetConX(int con) { this->SetCon(con); return this; }
+global func EnterX(object obj) { Enter(this, obj); return this; }
+global func SetLocalX(key, val)
+{
+ if(GetType(key) == C4V_Int || GetType(key) == C4V_Any) Local(key, this) = val;
+ else LocalN(key) = val;
+ return this;
+}
diff --git a/DTScopedVars.c b/DTScopedVars.c new file mode 100644 index 0000000..f64ccdc --- /dev/null +++ b/DTScopedVars.c @@ -0,0 +1,87 @@ +#strict 2 + +// TODO: ScopedVars with temporary target (like a reference to a function local var) + +static const ScopedVar_Global = 1; +static const ScopedVar_Local = 2; +static const ScopedVar_ArrayIndex = 3; + +global func GlobalVar(name) { return [ScopedVar_Global, name]; } +global func LocalVar(name, object target) { return [ScopedVar_Local, name, target || this]; } +global func ArrayVar(index, array scopedVar) { return [ScopedVar_ArrayIndex, scopedVar, index]; } + +global func &ScopedVar(array variable) +{ + if(!variable) + { + return 0; + } + if(variable[0] == ScopedVar_Global) + { + if(GetType(variable[1]) == C4V_String) + { + return GlobalN(variable[1]); + } + else + { + return Global(variable[1]); + } + } + else if(variable[0] == ScopedVar_Local) + { + if(GetType(variable[1]) == C4V_String) + { + return LocalN(variable[1], variable[2]); + } + else + { + return Local(variable[1], variable[2]); + } + } + else if(variable[0] == ScopedVar_ArrayIndex) + { + var index = variable[2]; + if(GetType(index) != C4V_Int && GetType(index) != C4V_Any) + { + index = ScopedVar(index); + } + return ScopedVar(variable[1])[index]; + } + else + { + return ScopedVar(CustomScopedVar(variable)); + } +} + +global func &CustomScopedVar() { return _inherited(...); } // this allows "overloading" this function even if the "overloading" function is loaded before + +global func CheckScopedVar(array variable) +{ + if(!variable) + { + return false; + } + + if(GetType(variable[0]) == C4V_Int) + { + if(variable[0] == ScopedVar_Global || variable[0] == ScopedVar_Local) + { + if(!variable[1] || GetType(variable[1]) == C4V_Int || (GetType(variable[1]) == C4V_String && variable[1] != "")) + { + return true; + } + } + + if(variable[0] == ScopedVar_ArrayIndex) + { + if(CheckScopedVar(variable[1]) && !variable[2] || (GetType(variable[2]) == C4V_Int && variable[2] >= 0)) + { + return true; + } + } + } + + return CheckCustomScopedVar(variable); +} + +global func CheckCustomScopedVar() { return _inherited(...); } diff --git a/DTTemplateFunctions.c b/DTTemplateFunctions.c new file mode 100644 index 0000000..860c9e1 --- /dev/null +++ b/DTTemplateFunctions.c @@ -0,0 +1,307 @@ +/*-- Template Functions --*/
+
+#strict 2
+
+static v;
+static TMPL_Funcs;
+static const TMPL_FuncArguments = 0;
+static const TMPL_FuncContents = 1;
+static const TMPL_FuncName = 2;
+static const TMPL_FuncCommands = 3;
+
+global func InitializeTemplateFunctions()
+{
+ if(GetType(v) != C4V_Array) v = [];
+ if(GetType(TMPL_Funcs) != C4V_Array) TMPL_Funcs = [];
+}
+
+global func DefineFunction(string name, arguments, commands)
+{
+ InitializeTemplateFunctions();
+
+ var anonymousFunction = Function(arguments, commands);
+
+ var function = [anonymousFunction[0], anonymousFunction[1], name, commands];
+
+ SetFunction(name, function);
+}
+
+global func SetFunction(string name, array function)
+{
+ var index = FindTemplateFunction(name);
+ if(index != -1)
+ {
+ TMPL_Funcs[index] = function;
+ }
+ else
+ {
+ TMPL_Funcs[GetLength(TMPL_Funcs)] = function;
+ }
+}
+
+global func RemoveFunction(string name)
+{
+ var index = FindTemplateFunction(name);
+ if(index != -1)
+ {
+ var i;
+ for(i = index; i < GetLength(TMPL_Funcs) - 1; ++i)
+ {
+ TMPL_Funcs[i] = TMPL_Funcs[i + 1];
+ }
+ TMPL_Funcs[GetLength(TMPL_Funcs) - 1] = 0;
+ }
+}
+
+global func Function(arguments, commands)
+{
+ if(!commands)
+ {
+ commands = arguments;
+ arguments = [];
+ }
+
+ if(GetType(arguments) == C4V_String) arguments = [arguments];
+ else if(arguments == 0) arguments = [];
+
+ if(GetType(commands) == C4V_String) commands = [commands];
+
+ var funcContents = [];
+ for(var command in commands)
+ {
+ var isArg = false;
+ var argument = "";
+ var funcContent = [];
+ var contentPart = "";
+ var escapeCount = 0;
+ for(var i = 0; i < GetLength(command); ++i)
+ {
+ var c = GetChar(command, i);
+ if(isArg)
+ {
+ if(c == 37) // %
+ {
+ if(argument == "")
+ {
+ contentPart = Format("%s%%", contentPart);
+ }
+ else
+ {
+ var index = GetIndexOf2(argument, arguments);
+ if(index == -1)
+ {
+ FatalError(Format("Function: Unknown argument-name %s", argument));
+ return;
+ }
+ else
+ {
+ funcContent[GetLength(funcContent)] = [index, escapeCount];
+ argument = "";
+ escapeCount = 0;
+ }
+ }
+ isArg = false;
+ }
+ else if(argument == "" && c == 47) // /
+ {
+ ++escapeCount;
+ }
+ else
+ {
+ if(contentPart != "")
+ {
+ funcContent[GetLength(funcContent)] = contentPart;
+ contentPart = "";
+ }
+
+ argument = Format("%s%c", argument, c);
+ }
+ }
+ else
+ {
+ if(c == 37) // %
+ {
+ isArg = true;
+ }
+ else if(c == 39) // '
+ {
+ contentPart = Format("%s\"", contentPart);
+ }
+ else
+ {
+ contentPart = Format("%s%c", contentPart, c);
+ }
+ }
+ }
+ if(isArg) FatalError(Format("Function: argument-reference \"%s\" not closed.", argument));
+ else if(contentPart) funcContent[GetLength(funcContent)] = contentPart;
+ funcContents[GetLength(funcContents)] = funcContent;
+ }
+
+ return [arguments, funcContents];
+}
+
+global func FindTemplateFunction(string name)
+{
+ var i = 0;
+ for(var function in TMPL_Funcs)
+ {
+ if(GetType(function) == C4V_Array && function[TMPL_FuncName] == name) return i;
+ ++i;
+ }
+ return -1;
+}
+
+global func F(string name, array args)
+{
+ return f(Func(name), args);
+}
+
+global func f(array function, array args)
+{
+ var ret;
+ for(var content in function[TMPL_FuncContents])
+ {
+ var command = "";
+ for(var contentPart in content)
+ {
+ if(GetType(contentPart) == C4V_Array)
+ {
+ var part = StringReplace("'", Serialize(args[contentPart[0]]), "\\\"");
+ for(var i = 0; i < contentPart[1]; ++i)
+ {
+ part = EscapeString(part);
+ }
+ command = Format("%s%s", command, part);
+ }
+ else command = Format("%s%s", command, contentPart);
+ }
+ ret = eval(command);
+ }
+ return ret;
+}
+
+global func DebugF(string function, array args)
+{
+ return DebugFunc(Func(function), args);
+}
+
+global func DebugFunc(array function, array args)
+{
+ var ret;
+ for(var content in function[TMPL_FuncContents])
+ {
+ var command = "";
+ for(var contentPart in content)
+ {
+ if(GetType(contentPart) == C4V_Array)
+ {
+ var part = StringReplace("'", Serialize(args[contentPart[0]]), "\\\"");
+ for(var i = 0; i < contentPart[1]; ++i)
+ {
+ part = EscapeString(part);
+ }
+ command = Format("%s%s", command, part);
+ }
+ else command = Format("%s%s", command, contentPart);
+ }
+ Log(command);
+ }
+ return ret;
+}
+
+global func Func(string name)
+{
+ var index = FindTemplateFunction(name);
+ if(index == -1)
+ {
+ FatalError(Format("Func: Unknown function %s.", name));
+ return;
+ }
+ return TMPL_Funcs[index];
+}
+
+global func SaveFunction(int plr, string name, array function)
+{
+ return SetPlrExtraDataArray(plr, Format("TemplateFunction_%s", name), function);
+}
+
+global func LoadFunction(int plr, string name, string loadAs)
+{
+ var function = GetPlrExtraDataArray(plr, Format("TemplateFunction_%s", name));
+ if(function == 0)
+ {
+ FatalError(Format("LoadFunction: Unknown function: \"%s\"", name));
+ return;
+ }
+ if(loadAs != 0)
+ {
+ SetFunction(loadAs, function);
+ }
+ return function;
+}
+
+global func DeleteFunction(int plr, string name)
+{
+ return SetPlrExtraDataString(plr, Format("TemplateFunction_%s", name), "");
+}
+
+global func CallCustom(callback, args)
+{
+ if(GetType(callback) == C4V_Array && GetLength(callback) >= 2 && GetType(callback[0]) == C4V_Array && GetType(callback[1]) == C4V_Array)
+ {
+ return f(callback, args);
+ }
+ else
+ {
+ return _inherited(callback, args, ...);
+ }
+}
+
+global func CheckCustomCallback(callback)
+{
+ if(GetType(callback) == C4V_Array && (GetLength(callback) == 2 || (GetLength(callback) == 4 && GetType(callback[2]) == C4V_String && GetType(callback[3]) == C4V_Array)) && GetType(callback[0]) == C4V_Array && GetType(callback[1]) == C4V_Array)
+ {
+ var stringOnlyChecks = [callback[0]];
+
+ if(GetLength(callback) == 4)
+ {
+ stringOnlyChecks[1] = callback[3];
+ }
+
+ for(var check in stringOnlyChecks)
+ {
+ for(var val in check)
+ {
+ if(GetType(val) != C4V_String)
+ {
+ return _inherited(callback, ...);
+ }
+ }
+ }
+
+ for(var contentParts in callback[1])
+ {
+ if(GetType(contentParts) != C4V_Array)
+ {
+ return _inherited(callback, ...);
+ }
+
+ for(var content in contentParts)
+ {
+ if(GetType(content) == C4V_String)
+ {
+ continue;
+ }
+
+ if(GetType(content) != C4V_Array || GetLength(content) != 2 || (content[0] && GetType(content[0]) == C4V_Int && content[0] < 0) || (content[1] && GetType(content[1]) == C4V_Int && content[1] < 0))
+ {
+ return _inherited(callback, ...);
+ }
+ }
+ }
+
+ return true;
+ }
+ return _inherited(callback, ...);
+}
diff --git a/DTTimer.c b/DTTimer.c new file mode 100644 index 0000000..ecc5885 --- /dev/null +++ b/DTTimer.c @@ -0,0 +1,26 @@ +#strict 2
+
+global func AddTimer(callback, int timer, object target, int prio)
+{
+ target = target || this;
+ return AddEffect("IntTimer", target, prio || 1, timer, target, 0, callback);
+}
+
+global func RemoveTimer(int id, object target)
+{
+ target = target || this;
+ return RemoveEffect(0, target, id);
+}
+
+global func FxIntTimerStart(object target, int effectNumber, int temp, callback)
+{
+ if(!temp)
+ {
+ EffectVar(0, target, effectNumber) = callback;
+ }
+}
+
+global func FxIntTimerTimer(object target, int effectNumber, int effectTime)
+{
+ return Call(EffectVar(0, target, effectNumber));
+}
diff --git a/DTTransform.c b/DTTransform.c new file mode 100644 index 0000000..07206c2 --- /dev/null +++ b/DTTransform.c @@ -0,0 +1,240 @@ +#strict 2 + +global func ResetTransform(overlays) +{ + for(var overlay in TransformOverlays(overlays)) + { + if(!overlay) SetObjDrawTransform(0, 0, 0, 0, 0, 0, this, overlay); + else SetObjDrawTransform(1000, 0, 0, 0, 1000, 0, this, overlay); + } +} + +global func SetTransform(array transforms, overlays) +{ + for(var overlay in TransformOverlays(overlays)) + { + ResetTransform(overlay); + AddTransform(transforms, overlay); + } +} + +global func AddTransform(array transforms, overlays) +{ + for(var overlay in TransformOverlays(overlays)) + { + for(var transform in transforms) + { + SetObjDrawTransform2(transform[0][0], transform[0][1], transform[0][2], transform[1][0], transform[1][1], transform[1][2], transform[2][0], transform[2][1], transform[2][2], overlay); + } + } +} + +global func TransformOverlays(overlays) +{ + if(!overlays || GetType(overlays) == C4V_Int) + { + if(overlays >= 0) return [overlays]; + else + { + var ret = []; + overlays = Abs(overlays); + for(var i = 0; i <= overlays; ++i) + { + ret[GetLength(ret)] = i; + } + return ret; + } + } + else if(GetType(overlays) == C4V_Array) + { + var ret = [], last; + last = overlays[0]; + var i = 1; + if(last < 0) + { + i = 0; + last = 0; + } + else + { + ret[0] = last; + } + for(; i < GetLength(overlays); ++i) + { + var overlay = overlays[i]; + if(overlay < 0) + { + overlay = Abs(overlay); + for(var j = last + 1; j <= overlay; ++j) + { + ret[GetLength(ret)] = j; + } + } + else + { + ret[GetLength(ret)] = overlay; + } + last = overlay; + } + + return ret; + } + else + { + FatalError("TransformOverlays: overlays must be a single integer or an array."); + } +} + +global func Rotate() { return RotateZ(...); } + +global func RotateX(int phi, int prec) +{ + prec = prec || 1; + + var cos = Cos(phi, 1000, prec); + var sin = Sin(phi, 1000, prec); + + return + [ + [1000, 0, 0], + [ 0, cos, -sin], + [ 0, sin, cos] + ]; +} + +global func RotateY(int phi, int prec) +{ + prec = prec || 1; + + var cos = Cos(phi, 1000, prec); + var sin = Sin(phi, 1000, prec); + + return + [ + [ cos, 0, sin], + [ 0, 1000, 0], + [-sin, 0, cos] + ]; +} + +global func RotateZ(int phi, int prec) +{ + prec = prec || 1; + + var cos = Cos(phi, 1000, prec); + var sin = Sin(phi, 1000, prec); + + return + [ + [cos, -sin, 0], + [sin, cos, 0], + [ 0, 0, 1000] + ]; +} + +global func Scale3D(int x, int y, int z) +{ + return + [ + [x, 0, 0], + [0, y, 0], + [0, 0, z] + ]; +} + +global func Scale2D(int x, int y) { return Scale3D(x, y, 1000); } + +global func ScaleX(int f) { return Scale3D(f, 1000, 1000); } +global func ScaleY(int f) { return Scale3D(1000, f, 1000); } +global func ScaleZ(int f) { return Scale3D(1000, 1000, f); } + +global func Translate2D(int x, int y, int prec) +{ + prec = prec || 1; + return + [ + [1000, 0, x * 1000 / prec], + [ 0, 1000, y * 1000 / prec], + [ 0, 0, 1000] + ]; +} + +global func TranslateX(int x, int prec) { return Translate2D(x, 0, prec); } +global func TranslateY(int y, int prec) { return Translate2D(0, y, prec); } + +global func MirrorX() +{ + return + [ + [-1000, 0, 0], + [ 0, 1000, 0], + [ 0, 0, 1000] + ]; +} + +global func MirrorY() +{ + return + [ + [1000, 0, 0], + [ 0, -1000, 0], + [ 0, 0, 1000] + ]; +} + +global func MirrorZ() // useless? +{ + return + [ + [1000, 0, 0], + [ 0, 1000, 0], + [ 0, 0, -1000] + ]; +} + +global func Skew2D(int x, int y) +{ + return + [ + [1000, x, 0], + [ y, 1000, 0], + [ 0, 0, 1000] + ]; +} + +global func SkewX(int x) { return Skew2D(x, 0); } +global func SkewY(int y) { return Skew2D(0, y); } + +global func Matrix3x3Multiply(array a, array b, int precision) +{ + return + [ + [(a[0][2] * b[2][0] + a[0][1] * b[1][0] + a[0][0] * b[0][0]) / precision, (a[0][2] * b[2][1] + a[0][1] * b[1][1] + a[0][0] * b[0][1]) / precision, (a[0][2] * b[2][2] + a[0][1] * b[1][2] + a[0][0] * b[0][2]) / precision], + [(a[1][2] * b[2][0] + a[1][1] * b[1][0] + a[1][0] * b[0][0]) / precision, (a[1][2] * b[2][1] + a[1][1] * b[1][1] + a[1][0] * b[0][1]) / precision, (a[1][2] * b[2][2] + a[1][1] * b[1][2] + a[1][0] * b[0][2]) / precision], + [(a[2][2] * b[2][0] + a[2][1] * b[1][0] + a[2][0] * b[0][0]) / precision, (a[2][2] * b[2][1] + a[2][1] * b[1][1] + a[2][0] * b[0][1]) / precision, (a[2][2] * b[2][2] + a[2][1] * b[1][2] + a[2][0] * b[0][2]) / precision] + ]; +} + +global func PreTransform(array transforms) // funzt nit +{ + if(GetLength(transforms) == 0) + { + FatalError("PreTransform called without transforms."); + } + else + { + var ret = transforms[0]; + for(var i = 1; i < GetLength(transforms); ++i) + { + ret = Matrix3x3Multiply(ret, transforms[i], 1000); + } + return ret; + } +} + +// Riesenschädl +// GetCursor(0)->SetTransform([TranslateY(8), RotateX(4), ScaleZ(400), TranslateY(-10)]) + +// Ähnlich Chipakyus Demo +// Schedule("FindObject(HUT2)->SetTransform([TranslateY(-20), RotateZ(++Global(0)), TranslateY(0), RotateX(-1), TranslateY(20)])", 1, 10000) +// Schedule("GetCursor(0)->SetTransform([TranslateY(-8), RotateZ(++Global(0)), TranslateY(0), RotateX(-2), TranslateY(8)])", 1, 10000) diff --git a/DTUtility.c b/DTUtility.c new file mode 100644 index 0000000..a747d33 --- /dev/null +++ b/DTUtility.c @@ -0,0 +1,744 @@ +#strict 2
+
+global func Isolate(object obj) // Puts the object in its own layer to prevent interaction
+{
+ obj || obj = this;
+ return obj->SetObjectLayer(obj);
+}
+
+global func GetIndexOf2(val, array arr) // Because GetIndexOf doesn't find Format("%c", GetChar("a", 0)) in ["a"]
+{
+ var i = 0;
+ for(var value in arr)
+ {
+ if(val == value) return i;
+ ++i;
+ }
+ return -1;
+}
+
+global func Serialize(value)
+{
+ if(GetType(value) == C4V_Array)
+ {
+ var first = true;
+ var ret = "[";
+ for(var val in value)
+ {
+ if(first)
+ {
+ first = false;
+ }
+ else
+ {
+ ret = Format("%s,", ret);
+ }
+ ret = Format("%s%s", ret, Serialize(val));
+ }
+ return Format("%s]", ret);
+ }
+ else if(GetType(value) == C4V_Bool) if(value) return "true"; else return "false";
+ else if(GetType(value) == C4V_C4ID) return Format("%i", value);
+ else if(GetType(value) == C4V_C4Object) return Format("Object(%d)", ObjectNumber(value));
+ else if(GetType(value) == C4V_Int || GetType(value) == C4V_Any) return Format("%d", value);
+ else if(GetType(value) == C4V_String) return Format("\"%s\"", EscapeString(value));
+}
+
+global func EscapeString(string value)
+{
+ var ret = "";
+ for(var i = 0; i < GetLength(value); ++i)
+ {
+ var c = GetChar(value, i);
+ if(c == 34) // "
+ {
+ ret = Format("%s\\\"", ret);
+ }
+ else if(c == 92) // \
+ {
+ ret = Format("%s\\\\", ret);
+ }
+ else
+ {
+ ret = Format("%s%c", ret, c);
+ }
+}
+return ret;
+}
+
+global func CreateEnum(string prefix, array enum)
+{
+ var log = Format("%c// This enum was created with CreateEnum(%s, %s);%c", 10, Serialize(prefix), Serialize(enum), 10);
+ var switch = "";
+
+ for(var i = 0; i < GetLength(enum); ++i)
+ {
+ log = Format("%s%cstatic const %s%s = %d;", log, 10, prefix, enum[i], i);
+
+ if(switch == "")
+ {
+ switch = Format("if(switchval == %s%s)%c{%c%c}%c", prefix, enum[i], 10, 10, 10, 10);
+ }
+ else
+ {
+ switch = Format("%selse if(switchval == %s%s)%c{%c%c}%c", switch, prefix, enum[i], 10, 10, 10, 10);
+ }
+ }
+
+ Log("%s%c%c// Template if-structure - replace switchval with the value to compare.%c%c%s", log, 10, 10, 10, 10, switch);
+}
+
+global func CreateBitField(string prefix, array flags)
+{
+ if(GetLength(flags) > 32)
+ {
+ FatalError("CreateBitField: A bitfield can only have a maximum of up to 32 flags.");
+ return;
+ }
+
+ var log = Format("%c// This bitfield was created with CreateBitField(%s, %s);%c", 10, Serialize(prefix), Serialize(flags), 10);
+
+ for(var i = 0, j = 1; i < GetLength(flags); ++i)
+ {
+ log = Format("%s%cstatic const %s%s = %d;", log, 10, prefix, flags[i], j);
+ j = j << 1;
+ }
+
+ Log("%s%c%c", log, 10, 10);
+}
+
+// pos >= 0 => begin at pos | pos < 0 => begin at GetLength(string) - pos
+// count = 0 => replace all | count > 0 replace a maximum of count occurences from starting from pos
+
+global func Lowercase(int c)
+{
+ if((c >= 65 && c <= 90) || (c >= 192 && c <= 214) || (c >= 216 && c <= 221)) return c + 32;
+ else return c;
+}
+
+global func StringLowercase(string string)
+{
+ var ret = "";
+ for(var i = 0; i < GetLength(string); ++i)
+ {
+ ret = Format("%s%c", ret, Lowercase(GetChar(string, i)));
+ }
+ return ret;
+}
+
+global func MultiStringLowercase(array strings)
+{
+ var ret = [];
+ for(var string in strings)
+ {
+ ret[GetLength(ret)] = StringLowercase(string);
+ }
+ return ret;
+}
+
+global func CaseInsensitive(int c, bool caseSensitive) // TODO
+{
+ if(caseSensitive) return c;
+ else return Lowercase(c);
+}
+
+global func StringConcatenate(array strings)
+{
+ var ret = strings[0];
+
+ for(var i = 1; i < GetLength(strings); ++i)
+ {
+ ret = Format("%s%s", ret, strings[i]);
+ }
+
+ return ret;
+}
+
+global func MultiStringReplace(find, strings, replace, bool caseInsensitive, int count, int pos, int maxpos)
+{
+ var returnString = false;
+ if(GetType(strings) == C4V_String)
+ {
+ strings = [strings];
+ returnString = true;
+ }
+ else if(GetType(strings) != C4V_Array) return strings;
+ if(GetType(find) == C4V_String) find = [find];
+ else if(GetType(find) != C4V_Array) return strings;
+ if(GetType(replace) == C4V_String) replace = [find];
+ else if(GetType(replace) != C4V_Array) return strings;
+
+ var ret = [];
+
+ for(var i = 0; i < GetLength(strings); ++i)
+ {
+ ret[i] = strings[i];
+ for(var j = 0; j < GetLength(find); ++j)
+ {
+ ret[i] = StringReplace(find[j], ret[i], replace[j % GetLength(replace)], caseInsensitive, count, pos, maxpos);
+ }
+ }
+
+ if(returnString) return ret[0];
+ else return ret;
+}
+
+global func StringReplace(string find, string string, string replace, bool caseInsensitive, int count, int pos, int maxpos)
+{
+ if(GetLength(find) == 0 || GetLength(string) == 0) return string;
+ var ret = "";
+ if(pos < 0) pos = GetLength() - pos;
+ if(maxpos < 0) maxpos = GetLength(string) - pos;
+ if(maxpos == 0) maxpos = GetLength(string);
+ if(pos < 0 || pos > GetLength(string) || maxpos < 0 || maxpos > GetLength(string) || count < 0) return string;
+ if(count == 0) count = -1;
+
+ for(var i = 0; i < pos; ++i)
+ {
+ ret = Format("%s%c", ret, GetChar(string, i));
+ }
+
+ var match = 0;
+
+ var i;
+
+ for(i = pos; i + GetLength(find) - match - 1 < maxpos && count != 0; ++i)
+ {
+ var c = GetChar(string, i);
+ if(CaseInsensitive(c, !caseInsensitive) == CaseInsensitive(GetChar(find, match), !caseInsensitive))
+ {
+ if(++match == GetLength(find))
+ {
+ ret = StringConcatenate([ret, replace]);
+ match = 0;
+ --count;
+ }
+ }
+ else
+ {
+ if(match != 0)
+ {
+ for(var j = i - match; j < i; ++j)
+ {
+ ret = Format("%s%c", ret, GetChar(string, j));
+ }
+ }
+ match = 0;
+ ret = Format("%s%c", ret, GetChar(string, i));
+ }
+ }
+
+ for(i -= match; i < GetLength(string); ++i)
+ {
+ ret = Format("%s%c", ret, GetChar(string, i));
+ }
+
+ return ret;
+}
+
+global func StringReplaceMulti(string find, string string, array replace)
+{
+ var ret = [];
+ for(var rep in replace)
+ {
+ ret[GetLength(ret)] = StringReplace(find, string, rep);
+ }
+ return ret;
+}
+
+global func MultiStringReplaceMulti(string string, array findReplace)
+{
+ var ret = [];
+
+ for(var j = 0; j < GetLength(findReplace[0][1]); ++j)
+ {
+ var part = string;
+ for(var i = 0; i < GetLength(findReplace); ++i)
+ {
+ part = StringReplace(findReplace[i][0], part, findReplace[i][1][j]);
+ }
+ ret[j] = part;
+ }
+
+ return ret;
+}
+
+global func GetMapValue(key, array map, default)
+{
+ for(var val in map)
+ {
+ if(val[0] == key) return val;
+ }
+ return default;
+}
+
+global func GetIDByName(string name, int category) // WARNING: desyncs between clients with different languages
+{
+ var i, id;
+ while(id = GetDefinition(i++, category))
+ {
+ if(GetName(0, id) == name) return id;
+ }
+ return 0;
+}
+
+global func GetIDsByName(string name, int category) // WARNING: desyncs between clients with different languages
+{
+ var i, id, ret = [];
+ while(id = GetDefinition(i++, category))
+ {
+ if(GetName(0, id) == name)
+ {
+ ret[GetLength(ret)] = id;
+ }
+ }
+ return ret;
+}
+
+global func ArrayConcatenate(array arrays)
+{
+ var ret = [];
+ for(var arr in arrays)
+ {
+ for(var val in arr)
+ {
+ ret[GetLength(ret)] = val;
+ }
+ }
+ return ret;
+}
+
+global func SetPlrExtraDataString(int plr, string name, string data)
+{
+ var part = 0;
+ var i;
+ for(i = 0; i < GetLength(data); ++i)
+ {
+ var c = GetChar(data, i);
+
+ if((i % 4) == 0 && i != 0)
+ {
+ SetPlrExtraData(plr, Format("%s%d", name, i/4 - 1), part);
+ part = 0;
+ }
+
+ part |= (c << ((i % 4) * 8));
+ }
+
+ if(part != 0)
+ {
+ SetPlrExtraData(plr, Format("%s%d", name, i/4), part);
+ }
+
+ i = i/4 + 1;
+ while(GetPlrExtraData(plr, Format("%s%d", name, i)))
+ {
+ SetPlrExtraData(plr, Format("%s%d", name, i++), 0);
+ }
+}
+
+global func GetPlrExtraDataString(int plr, string name)
+{
+ var ret = "";
+ var part = true;
+ for(var i = 0; part != 0; ++i)
+ {
+ part = CastInt(GetPlrExtraData(plr, Format("%s%d", name, i)));
+ for(var j = 0; j < 4; ++j)
+ {
+ var c = (part >> (j * 8)) & 0xFF;
+ if(c == 0)
+ {
+ part = 0;
+ break;
+ }
+ else
+ {
+ ret = Format("%s%c", ret, c);
+ }
+ }
+ }
+ return ret;
+}
+
+global func SetPlrExtraDataArray(int plr, string name, array arr)
+{
+ return SetPlrExtraDataString(plr, name, Serialize(arr));
+}
+
+global func GetPlrExtraDataArray(int plr, string name)
+{
+ var function = GetPlrExtraDataString(plr, name);
+ if(function != "")
+ {
+ return eval(function);
+ }
+}
+
+global func EnableScripting()
+{
+ AddMsgBoardCmd("s", "ScriptingFunc(\"%s\", %player%)", C4MSGCMDR_Escaped);
+}
+
+global func ScriptingFunc(string script, int player)
+{
+ Log("-> %s", script);
+ Log("= %v (by %s)", eval(script), GetTaggedPlayerName(player));
+}
+
+global func ParseInt(string int, bool hex)
+{
+ if(GetLength(int) == 0)
+ {
+ return "";
+ }
+ var ret = 0, neg = false;
+ for(var i = 0; i < GetLength(int); ++i)
+ {
+ var c = GetChar(int, i);
+ if(i == 0)
+ {
+ if(c == 45) // "-"
+ {
+ neg = true;
+ continue;
+ }
+ else if(c == 43) // "+"
+ {
+ continue;
+ }
+ }
+ c -= 48; // "0" == 48
+ if(c < 0 || ((!hex && c > 9) || (hex && c > 54))) // "f" - "0" == 54
+ {
+ return "";
+ }
+ if(hex)
+ {
+ ret = ret << 4;
+ }
+ else
+ {
+ ret *= 10;
+ }
+ if(c > 9)
+ {
+ c -= 39;
+ }
+ ret += c;
+ }
+ return ret * (1 - (2 * neg));
+}
+
+global func ParseFloat(string float, int precision) // precision = number of digits after decimal point and multiplier of 10^precision
+{
+ precision = precision || 3;
+ if(GetLength(float) == 0)
+ {
+ return "";
+ }
+ var ret = 0, neg = false, decimalPoint = -1;
+ for(var i = 0; i < GetLength(float); ++i)
+ {
+ if(decimalPoint != -1 && decimalPoint + precision < i)
+ {
+ // out of precision
+ break;
+ }
+
+ var c = GetChar(float, i);
+ if(i == 0)
+ {
+ if(c == 45) // "-"
+ {
+ neg = true;
+ continue;
+ }
+ else if(c == 43) // "+"
+ {
+ continue;
+ }
+ }
+ c -= 48; // "0" == 48
+ if(c < 0 || c > 9)
+ {
+ if((c == -2 || c == -4) && decimalPoint == -1) // "." || ","
+ {
+ decimalPoint = i;
+ continue;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ ret *= 10;
+ ret += c;
+ }
+ if(decimalPoint == -1)
+ {
+ decimalPoint = i - 1;
+ }
+
+ for(; i <= decimalPoint + precision; ++i)
+ {
+ ret *= 10;
+ }
+
+ return ret * (1 - (2 * neg));
+}
+
+global func CreateFilledArray()
+{
+ var ret = [];
+ for(var i = 9; i >= 0; --i)
+ {
+ if(Par(i))
+ {
+ ret[i] = Par(i);
+ }
+ }
+ return ret;
+}
+
+global func Find_Procedure(string proc)
+{
+ return [C4FO_Func, "Find_ProcedureCheck", proc];
+}
+
+global func Find_ProcedureCheck(string proc)
+{
+ return proc == GetProcedure();
+}
+
+global func GetSolidMask(object obj)
+{
+ obj = obj || this;
+ return
+ [
+ GetObjectVal("SolidMask", 0, obj, 0), GetObjectVal("SolidMask", 0, obj, 1),
+ GetObjectVal("SolidMask", 0, obj, 2), GetObjectVal("SolidMask", 0, obj, 3),
+ GetObjectVal("SolidMask", 0, obj, 4), GetObjectVal("SolidMask", 0, obj, 5)
+ ];
+}
+
+// getValue:
+// 0 - offset index (the preferred way is to always get the offset index first and to pass the result to following calls for performance reasons)
+// 1 - overlay ID
+// 2 - overlay mode
+// 3 - graphics definition ID
+// 4 - graphics name
+// 5 - action name
+// 6 - blit mode
+// 7 - index of Transformation-matrix
+// 8 - enumerated overlay object (i.e. object number of the overlay object); WARNING: this is only valid and true directly after saving or loading a savegame
+
+global func GetOverlayValueByIndex(int index, int startIndex, int getValue, object obj) // startIndex can be given as a valid index (retrieved with this function beforehand) and the asked index is used as offset (better performance for iterating over all indices)
+{
+ if(getValue < 0 || getValue > 8)
+ {
+ // invalid getValues could cause infinite loops
+ return -2;
+ }
+ obj = obj || this;
+ var found = false;
+ if(index == 0)
+ {
+ if(getValue == 0)
+ {
+ if(GetObjectVal("GfxOverlay", 0, obj, startIndex) == 0)
+ {
+ // there is no such overlay
+ return -1;
+ }
+ else
+ {
+ return startIndex;
+ }
+ }
+ else if(getValue == 1)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, startIndex);
+ }
+ found = true;
+ }
+ for(var i = startIndex + 1, foundIndex = 0; ;) // skip overlay ID
+ {
+ var val = GetObjectVal("GfxOverlay", 0, obj, i);
+ if(val == 0)
+ {
+ // there is no overlay left
+ return -1;
+ }
+ if(val == GFXOV_MODE_Object)
+ {
+ // this is the overlay mode GFXOV_MODE_Object. Graphics-Definition and -Name are left out
+ if(found && (getValue == 3 || getValue == 4))
+ {
+ return 0;
+ }
+ else if(found && getValue == 2)
+ {
+ return GFXOV_MODE_Object;
+ }
+ }
+ else if(GetType(val) == C4V_C4ID)
+ {
+ if(found)
+ {
+ if(getValue == 3)
+ {
+ return val;
+ }
+ else if(getValue == 4)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i + 1);
+ }
+ }
+ i += 2; // skip Graphics-Definition and -Name, so i points to OverlayMode here too
+ if(found && getValue == 2)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i);
+ }
+ }
+ else
+ {
+ //something went wrong already
+ return -3;
+ }
+
+ if(found)
+ {
+ if(getValue == 5)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i + 1);
+ }
+ else if(getValue == 6)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i + 2);
+ }
+ else if(getValue == 7)
+ {
+ return i + 4;
+ }
+ }
+
+ i += 10; // this is either the last row of the Transformation matrix or the Color-Modulation
+ val = GetObjectVal("GfxOverlay", 0, obj, i);
+
+ if(GetType(val) == C4V_String)
+ {
+ // part of the matrix, skip it
+ i += 3;
+ }
+
+ if(found && getValue == 8)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i + 2);
+ }
+
+ i += 3; // and the rest
+
+ if(++foundIndex == index)
+ {
+ if(GetObjectVal("GfxOverlay", 0, obj, i) == 0)
+ {
+ // there is no overlay left
+ return -1;
+ }
+ else
+ {
+ found = true;
+ if(getValue == 0)
+ {
+ return i;
+ }
+ else if(getValue == 1)
+ {
+ return GetObjectVal("GfxOverlay", 0, obj, i);
+ }
+ }
+ }
+
+ ++i; // skip the next overlay ID
+ }
+}
+
+global func GetOverlayValueOffsetByID(int overlay, object obj)
+{
+ obj = obj || this;
+
+ if(overlay != 0)
+ {
+ var offset = 0, diffIndex = 0;
+ while((offset = obj->GetOverlayValueByIndex(diffIndex, offset)) >= 0)
+ {
+ if(GetOverlayValueByIndex(0, offset, 1) == overlay)
+ {
+ return offset;
+ }
+ diffIndex = 1;
+ }
+ }
+
+ return -1;
+}
+
+global func GetObjDrawTransform(int overlay, int overlayOffset, object obj)
+{
+ obj = obj || this;
+ if(overlay == 0)
+ {
+ var first = GetObjectVal("DrawTransform", 0, obj, 0);
+ if(first == 0)
+ {
+ return [1000, 0, 0, 0, 1000, 0];
+ }
+ var ret = [ParseFloat(first, 3), ParseFloat(GetObjectVal("DrawTransform", 0, obj, 1), 3), ParseFloat(GetObjectVal("DrawTransform", 0, obj, 2), 3), ParseFloat(GetObjectVal("DrawTransform", 0, obj, 3), 3), ParseFloat(GetObjectVal("DrawTransform", 0, obj, 4), 3), ParseFloat(GetObjectVal("DrawTransform", 0, obj, 5), 3)];
+
+ var rest = GetObjectVal("DrawTransform", 0, obj, 7); // 6 is left out intentionally, because its only FlipDir (used internally for Actions with FlipDir)
+ if(GetType(rest) == C4V_String) // the last 3 matrix-values are only decompiled if they are not the default of [0, 0, 1.0]
+ {
+ SetLength(ret, 9);
+ ret[6] = ParseFloat(rest, 3);
+ ret[7] = ParseFloat(GetObjectVal("DrawTransform", 0, obj, 8), 3);
+ ret[8] = ParseFloat(GetObjectVal("DrawTransform", 0, obj, 9), 3);
+ }
+
+ return ret;
+ }
+ else
+ {
+ var index = 0;
+ if(overlay == -1)
+ {
+ index = overlayOffset;
+ }
+ else
+ {
+ index = obj->GetOverlayValueOffsetByID(overlay);
+ }
+ if(index < 0)
+ {
+ return index;
+ }
+ index = obj->GetOverlayValueByIndex(0, index, 7);
+ if(index < 0)
+ {
+ return index;
+ }
+
+ var ret = [ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index), 3), ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 1), 3), ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 2), 3), ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 3), 3), ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 4), 3), ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 5), 3)];
+
+ var rest = GetObjectVal("GfxOverlay", 0, obj, index + 7); // 6 is left out intentionally, because its only FlipDir (used internally for Actions with FlipDir)
+ if(GetType(rest) == C4V_String) // the last 3 matrix-values are only decompiled if they are not the default of [0, 0, 1.0]
+ {
+ SetLength(ret, 9);
+ ret[6] = ParseFloat(rest, 3);
+ ret[7] = ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 8), 3);
+ ret[8] = ParseFloat(GetObjectVal("GfxOverlay", 0, obj, index + 9), 3);
+ }
+
+ return ret;
+ }
+}
|
