! RemoveObject() in Destruction() aufzurufen ist sooo sinnvoll
[Luftherrschaft.git] / Luftherrschaft.c4d / Helpers.c4d / Rope2.c4d / Script.c
blob9eeaa02815734ff8b54ca81b844e83bc45bb7ebf
1 /*-- Das Seil --*/
3 #strict 2
5 local Length, CalcedLength;
7 /*
8 Unbenannte lokale Variablen
9 0 - 82
10 1 - 82
11 2 - Mittigster Vertex von ActionTarget 1
12 3 - '' '' '' ActionTarget 2
15 protected func Initialize() {
16 Local(0)=82;
17 Local(1)=82;
18 return 1;
21 public func CalcLength(object Target1, object Target2) {
22 // Anzahl Paare
23 var i=GetVertexNum() - 1;
24 var Count=0;
25 // für jedes Paar berechnen
26 while (i--) Count += VerticeLength (i, Target1, Target2);
27 return Count;
30 private func VerticeLength(int i,object Target1,object Target2) {
31 // erster Vertex: Geschwindigkeit von 1.Actiontarget berücksichtigen
32 if(i == 0)
33 return Distance(GetVertex (0) + GetXDir (Target1) / 2,GetVertex (0, 1) + GetYDir (Target1) / 2,GetVertex (1),GetVertex (1, 1));
34 // vorletzter Vertex: Geschwindigkeit von 2.Actiontarget berücksichtigen
35 if(i == (GetVertexNum () - 2))
36 return Distance(GetVertex (i),GetVertex (i, 1),GetVertex (i + 1) + GetXDir (Target2) / 2,GetVertex (i + 1, 1) + GetYDir (Target2)) / 2;
37 // Ansonsten nur die Positionen
38 return Distance(GetVertex (i),GetVertex (i, 1),GetVertex (i + 1),GetVertex (i + 1, 1));
41 public func MoveRope(object pObj1,object pObj2) {
42 var a,b;
43 // Hier, weil das Seil immer verschwinden soll, wenn ein angeknotetes Objekt verschwindet.
44 if(!pObj1 || !pObj2) return RemoveObject();
45 // Wir brauchen mindesten 3 Vertices, damit die Algorithmen funktionieren
46 if(GetVertexNum () < 3)
47 InsertVertex(1, (GetVertex (0) + GetVertex (1)) / 2, (GetVertex (0, 1) + GetVertex (1, 1)) / 2);
48 SetRopeEnd(pObj1, 0, Local(2), 2);
49 SetRopeEnd(pObj2, GetVertexNum () - 1, Local (3), -2);
50 var vertexdistance = 7 + 3 * GetVertexNum ();
51 // für jeden Vertex ausführen
52 for(var i = GetVertexNum () - 2; i > 0; i--) {
53 // Neue Position des Vertices
54 a = (GetVertex (i - 1) + GetVertex (i + 1)) / 2;
55 b = (GetVertex (i - 1, 1) + GetVertex (i + 1, 1)) / 2;
56 // Überschüssige Vertices, die nahe genug aneinander sind entfernen
57 if(GetVertexNum () > 3)
58 if(Distance(GetVertex (i - 1, 0), GetVertex (i - 1, 1), GetVertex (i + 1, 0), GetVertex (i + 1, 1)) < vertexdistance)
59 if(PathFree(GetVertex (i - 1, 0), GetVertex (i - 1, 1), GetVertex (i + 1, 0), GetVertex (i + 1, 1))) {
60 RemoveVertex (i);
61 continue;
63 // bei zu langem Abstand einen neuen Vertex einfügen
64 if(Distance(GetVertex(i - 1, 0), GetVertex (i - 1, 1), GetVertex (i, 0), GetVertex (i, 1)) > (5 + vertexdistance)) {
65 InsertVertex(i, (GetVertex (i - 1, 0) + GetVertex (i, 0)) / 2, (GetVertex (i - 1, 1) + GetVertex (i, 1)) / 2);
66 continue;
68 // Wenn durch verschieben des Vertex das Seil durch solides ginge, nicht verschieben, und bei genug Platz einen zusätzlichen Vertex einfügen
69 if(!PathFree (a, b, GetVertex (i - 1), GetVertex (i - 1, 1))) {
70 if(Distance (GetVertex (i - 1, 0), GetVertex (i - 1, 1), GetVertex (i, 0), GetVertex (i, 1)) > vertexdistance)
71 InsertVertex (i, (GetVertex (i-1, 0)+GetVertex (i, 0))/2, (GetVertex (i-1, 1)+GetVertex (i, 1))/2);
72 continue;
74 if(!PathFree (a, b, GetVertex (i + 1), GetVertex (i + 1, 1))) {
75 if(Distance (GetVertex (i+1, 0),GetVertex (i+1, 1),GetVertex (i, 0),GetVertex (i, 1)) > vertexdistance)
76 InsertVertex (i+1, (GetVertex (i+1, 0) + GetVertex (i, 0))/2, (GetVertex (i+1, 1) + GetVertex (i, 1))/2);
77 continue;
79 SetVertex (i, 0, a);
80 SetVertex (i, 1, b);
82 return 1;
85 func SetRopeEnd(object pObj,int iRopeVertex,int iObjVertex,int iWhichEnd) {
86 var x, y;
87 x = GetX (pObj) + GetVertex (iObjVertex, 0, pObj);
88 y = GetY (pObj) + GetVertex (iObjVertex, 1, pObj);
89 // Wenn durch die Bewegung des angebundenen Objekts das Seil durch solides ginge,
90 // einen Vertex an der letzten Position des Objekts einfügen
91 // wenn das Objekt selbst in fester Materie steckt, hülfe das auch nichts
92 if(!GBackSolid (x - GetX (), y - GetY ())) {
93 if(!PathFree (x, y, GetVertex(iRopeVertex + iWhichEnd, 0), GetVertex (iRopeVertex + iWhichEnd, 1))) {
94 InsertVertex (iRopeVertex - BoundBy (iWhichEnd, -1, 0), x, y);
96 else {
97 SetVertex (iRopeVertex, 0, x);
98 SetVertex (iRopeVertex, 1, y);
101 return 1;
104 private func InsertVertex(int iIndex,int iX,int iY) {
105 if (!AddVertex ()) return 0;
106 for (var i = GetVertexNum () - 1; i > iIndex; i-- ) {
107 SetVertex (i, 0, GetVertex (i - 1, 0));
108 SetVertex (i, 1, GetVertex (i - 1, 1));
110 SetVertex (iIndex, 0, iX);
111 SetVertex (iIndex, 1, iY);
112 return (1);
115 /* ActionCall From Connect */
117 func Connecting() {
118 var Target1 = GetRealContainer(GetActionTarget(0));
119 var Target2 = GetRealContainer(GetActionTarget(1));
120 MoveRope(GetActionTarget(0), GetActionTarget(1));
121 if(Target1 == Target2) return 0;
122 if(!Target1 || !Target2) return 0;
123 CalcedLength = CalcLength(Target1, Target2);
124 var Difference = CalcedLength - Length;
125 Length = Max(Length + GetActionTarget(0)->~RopeAskChangeLength(Difference, this), 3);
126 Length = Max(Length + GetActionTarget(1)->~RopeAskChangeLength(Difference, this), 3);
127 Difference = CalcedLength - Length;
128 if(Difference <= 0) return 0;
129 var iMass = GetMass(Target1) + GetMass (Target2);
130 Do_Stuff(Target1, Target2, iMass, Difference, 1, Local(2));
131 Do_Stuff(Target2, Target1, iMass, Difference, GetVertexNum () - 2, Local(3));
132 return 1;
135 func Do_Stuff(object pPullingObject,object Target2,int iMass,int iDifference,int RopeVertex,int ObjVertex) {
136 var Strength = (iDifference * GetMass(Target2)) / iMass;
137 // Wenn Crewmember, dann wird Physical Fight miteingerechnet: Je größer, desto weniger wird gezogen
138 // Masse: Je schwerer das gegenüberliegende Objekt, desto mehr wird gezogen
139 if(GetProcedure(pPullingObject) == "Walk")
140 Strength = Max(0, Strength - (GetPhysical ("Fight", 0, pPullingObject) / 30000));
141 if(GetProcedure(pPullingObject) == "Float")
142 Strength = Max(0, Strength - (GetPhysical ("Float", 0, pPullingObject) / 100));
143 PullObject(GetVertex(RopeVertex), GetVertex(RopeVertex, 1), Strength, pPullingObject, ObjVertex);
146 private func PullObject(int toX,int toY,int length,object obj,int vtx) {
147 var len = Min(length,Distance(toX, toY,GetX(obj) + GetVertex(vtx, 0, obj), GetY (obj)+GetVertex (vtx, 1, obj)));
148 var iAngle = MakeThisAngleUseful(Angle(GetX (obj)+GetVertex (vtx, 0, obj), GetY (obj)+GetVertex (vtx, 1, obj), toX, toY), -180, +180);
149 var iAngle2 = MakeThisAngleUseful(Angle(0, 0, GetVertex (vtx, 0, obj), GetVertex (vtx, 1, obj)), -180, +180);
150 var x = Sin(iAngle, len*10);
151 var y = Cos(iAngle, len*10);
152 if(Stuck (obj)) return 0;
153 SetXDir(BoundBy(GetXDir (obj, 100) + x, -1000, 1000), obj, 100);
154 SetYDir(BoundBy(GetYDir (obj, 100) - y, -1000, 1000), obj, 100);
155 SetRDir(GetRDir(obj, 100) + (iAngle - iAngle2) / 10, obj, 100);
156 if (length > 30)
157 SetPosition (GetX (obj) + BoundBy (x,-1,1), GetY (obj) - BoundBy (y,-1,1), obj);
160 func MakeThisAngleUseful (winkel, m, p) {
161 while (winkel > p)
162 winkel = winkel - 360;
163 while (winkel < m)
164 winkel = winkel + 360;
165 return winkel;
168 public func Activate(object obj1,object obj2) {
169 Local(2) = GetMiddlestVertex(obj1);
170 Local(3) = GetMiddlestVertex(obj2);
171 // Vertices erzeugen/ändern
172 SetVertex(0, 0, GetX (obj1) + GetVertex (Local (2), 0, obj1));
173 SetVertex(0, 1, GetY (obj1) + GetVertex (Local (2), 1, obj1));
174 SetVertex(1, 0, GetX (obj2) + GetVertex (Local (3), 0, obj2));
175 SetVertex(1, 1, GetY (obj2) + GetVertex (Local (3), 1, obj2));
176 SetAction("Connect", obj1, obj2);
177 Length = CalcLength();
180 public func CheckConVertices () {
181 Local(2) = GetMiddlestVertex (GetActionTarget ());
182 Local(3) = GetMiddlestVertex (GetActionTarget (1));
185 /* Mit SetObject kann man die angeknüpften Objekte ändern. num=0 für Actiontarget0 und num=1 für Actiontarget1 */
187 public func SetObject(object obj,int num) {
188 // keine Gebäude
189 if (GetCategory(obj) & C4D_Structure) return 0;
190 // 1.Actiontarget
191 if (num == 0) {
192 // Action und 2.Actiontarget bleiben erhalten
193 Local(2) = GetMiddlestVertex (obj);
194 SetAction("Connect", obj, GetActionTarget(1));
196 // 2.Actiontarget
197 if(num == 1) {
198 Local(3) = GetMiddlestVertex(obj);
199 SetAction("Connect", GetActionTarget(), obj);
201 return 1;
204 public func LineBreak(object pBreak) {
205 Sound ("LineBreak");
206 if(!pBreak) BreakMessage();
207 return 1;
210 func BreakMessage() {
211 // Meldung bei Leitungsbausatz am einen oder anderen Ende ausgeben
212 var pObj = GetActionTarget(0);
213 if(GetID(pObj) != LNKT)
214 pObj = GetActionTarget(1);
215 Message("$RopeBroken$",pObj);
216 return 1;
219 public func GetLength () { return (Length); }
221 protected func Destruction () {
222 // Benachrichtigungen
223 if(GetActionTarget(0)) GetActionTarget(0)->~RopeBreak(GetID(GetActionTarget(1)));
224 if(GetActionTarget(1)) GetActionTarget(1)->~RopeBreak(GetID(GetActionTarget(0)));