main.cpp/physics.h: add some (somewhat icky) compile fixes for OS X
[openc2e.git] / caosVM_motion.cpp
blobb4482c101c5f089db41faa93ffde724c6aadf533
1 /*
2 * caosVM_agent.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue Jun 01 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "caosVM.h"
21 #include "openc2e.h"
22 #include "Agent.h"
23 #include "AgentRef.h"
24 #include "World.h"
25 #include "Engine.h" // version
26 #include <iostream>
27 #include <boost/format.hpp>
28 using std::cerr;
30 /**
31 ELAS (command) elas (integer)
32 %status maybe
34 Sets the elasticity (in other words, bounciness) of the TARG agent.
36 void caosVM::c_ELAS() {
37 VM_VERIFY_SIZE(1)
38 VM_PARAM_INTEGER(elas)
40 valid_agent(targ);
41 targ->elas = elas;
44 /***
45 ELAS (integer)
46 %status maybe
48 Returns the elasticity of the TARG agent.
50 void caosVM::v_ELAS() {
51 VM_VERIFY_SIZE(0)
53 valid_agent(targ);
54 result.setInt(targ->elas);
57 /**
58 MVTO (command) x (float) y (float)
59 %status maybe
60 %pragma variants c1 c2 cv c3 sm
61 %cost c1,c2 1
63 Places the TARG agent at the given x/y position in the world (using the upper left hand corner of the agent).
65 void caosVM::c_MVTO() {
66 VM_VERIFY_SIZE(2)
67 VM_PARAM_FLOAT(y)
68 VM_PARAM_FLOAT(x)
69 valid_agent(targ);
70 targ->moveTo(x, y);
73 /**
74 MVBY (command) x (float) y (float)
75 %status maybe
76 %pragma variants c1 c2 cv c3 sm
77 %cost c1,c2 1
79 Changes the TARG agent's position by the given relative distances.
81 void caosVM::c_MVBY() {
82 VM_PARAM_FLOAT(y)
83 VM_PARAM_FLOAT(x)
85 valid_agent(targ);
86 targ->moveTo(targ->x + x, targ->y + y);
89 /**
90 VELX (variable)
91 %status maybe
92 %pragma variants c2 cv c3 sm
94 Returns the current horizontal velocity, in pixels/tick, of the TARG agent.
96 void caosVM::v_VELX() {
97 valid_agent(targ);
98 valueStack.push_back(targ->velx);
100 void caosVM::s_VELX() {
101 VM_PARAM_VALUE(newvalue)
102 caos_assert(newvalue.hasDecimal());
104 valid_agent(targ);
105 targ->velx = newvalue;
109 VELY (variable)
110 %status maybe
111 %pragma variants c2 cv c3 sm
113 Returns the current vertical velocity, in pixels/tick, of the TARG agent.
115 void caosVM::v_VELY() {
116 valid_agent(targ);
117 valueStack.push_back(targ->vely);
119 void caosVM::s_VELY() {
120 VM_PARAM_VALUE(newvalue)
121 caos_assert(newvalue.hasDecimal());
123 valid_agent(targ);
124 targ->vely = newvalue;
126 // a whole bunch of Creatures 2 scripts/COBs depend on this ('setv vely 0' to activate gravity)
127 if (engine.version == 2) targ->grav.setInt(1);
131 OBST (float) direction (integer)
132 %status maybe
133 %pragma variants cv c3 sm
135 Returns the distance from the TARG agent to the nearest wall that it might collide with in the given direction.
136 (except right now it just gives the direction to the nearest wall at world edge - fuzzie)
138 void caosVM::v_OBST() {
139 VM_VERIFY_SIZE(1)
140 VM_PARAM_INTEGER(direction) caos_assert(direction >= 0); caos_assert(direction <= 3);
143 * TODO: CL's docs say to return "a very large number" if distance is greater than rnge - if (!collided)?
144 * TODO: c2 docs say "from the centre point of TARG".. same in c2e? or do we need a separate function?
145 * also, this code is untested :) - fuzzie
148 valid_agent(targ);
150 Point src = targ->boundingBoxPoint(direction);
151 Point dest = src;
153 switch (direction) {
154 case 0: // left
155 dest.x -= targ->range.getFloat(); break;
156 case 1: // right
157 dest.x += targ->range.getFloat(); break;
158 case 2: // top
159 dest.y -= targ->range.getFloat(); break;
160 case 3: // bottom
161 dest.y += targ->range.getFloat(); break;
164 shared_ptr<Room> ourRoom = world.map.roomAt(src.x, src.y);
165 if (!ourRoom) {
166 // TODO: is this correct behaviour?
167 result.setFloat(0.0f);
168 return;
171 unsigned int dummy1; Line dummy2; Point point;
172 bool collided = world.map.collideLineWithRoomSystem(src, dest, ourRoom, point, dummy2, dummy1, targ->perm);
174 switch (direction) {
175 case 0: result.setFloat(src.x - point.x); break;
176 case 1: result.setFloat(point.x - src.x); break;
177 case 2: result.setFloat(src.y - point.y); break;
178 case 3: result.setFloat(point.y - src.y); break;
183 OBST (integer) direction (integer)
184 %status maybe
185 %pragma variants c2
186 %pragma implementation caosVM::v_OBST_c2
188 Returns the distance from the TARG agent to the nearest wall that it might collide with in the given direction.
190 void caosVM::v_OBST_c2() {
191 VM_PARAM_INTEGER(direction)
193 valid_agent(targ);
195 int dx = 0, dy = 0;
196 switch (direction) {
197 case 0: dx = -10000; break; // left
198 case 1: dx = 10000; break; // right
199 case 2: dy = -10000; break; // up
200 case 3: dy = 10000; break; // down
201 default: caos_assert(false);
204 Point src = targ->boundingBoxPoint(direction);
206 Point deltapt(0,0);
207 double delta = 1000000000;
208 bool collided = false;
210 targ->findCollisionInDirection(direction, src, dx, dy, deltapt, delta, collided, false);
212 if (!collided)
213 result.setInt(INT_MAX);
214 else
215 result.setInt(abs(deltapt.x + deltapt.y)); // only one will be set
219 TMVB (integer) deltax (float) deltay (float)
220 %status maybe
222 Returns 1 if the TARG agent could move by (deltax, deltay) and still be in room system, or 0 otherwise.
224 void caosVM::v_TMVB() {
225 VM_PARAM_FLOAT(deltay)
226 VM_PARAM_FLOAT(deltax)
228 valid_agent(targ);
230 if (targ->validInRoomSystem(Point(targ->x + deltax, targ->y + deltay), targ->getWidth(), targ->getHeight(), targ->perm))
231 result.setInt(1);
232 else
233 result.setInt(0);
237 TMVT (integer) x (float) y (float)
238 %status maybe
240 Returns 1 if the TARG agent could move to (x, y) and still be in room system, or 0 if otherwise.
242 void caosVM::v_TMVT() {
243 VM_VERIFY_SIZE(2)
244 VM_PARAM_FLOAT(y)
245 VM_PARAM_FLOAT(x)
247 valid_agent(targ);
249 if (targ->validInRoomSystem(Point(x, y), targ->getWidth(), targ->getHeight(), targ->perm))
250 result.setInt(1);
251 else
252 result.setInt(0);
256 TMVF (integer) x (float) y (float)
257 %status stub
259 Returns 1 if the TARG Creature could move foot to (x, y) and still be in room system, or 0 if otherwise.
261 void caosVM::v_TMVF() {
262 VM_VERIFY_SIZE(2)
263 VM_PARAM_FLOAT(y)
264 VM_PARAM_FLOAT(x)
266 valid_agent(targ);
267 result.setInt(1); // TODO: don't hardcode
271 ACCG (command) accel (float)
272 %status maybe
274 Sets the TARG agent's free-fall acceleration, in pixels/tick squared.
276 void caosVM::c_ACCG() {
277 VM_VERIFY_SIZE(1)
278 VM_PARAM_FLOAT(accel)
280 valid_agent(targ);
281 targ->accg = accel;
285 ACCG (float)
286 %status maybe
288 Returns the TARG agent's free-fall acceleration, in pixels/tick squared.
290 void caosVM::v_ACCG() {
291 VM_VERIFY_SIZE(0)
293 valid_agent(targ);
294 result.setFloat(targ->accg.getFloat());
298 ACCG (variable)
299 %status maybe
300 %pragma variants c2
301 %pragma implementation caosVM::v_ACCG_c2
302 %pragma saveimpl caosVM::s_ACCG_c2
304 Returns the TARG agent's free-fall acceleration, in pixels/tick squared.
306 CAOS_LVALUE_TARG_SIMPLE(ACCG_c2, targ->accg)
309 AERO (command) aero (float)
310 %status maybe
312 Sets the aerodynamics of the TARG agent to the given float value.
314 void caosVM::c_AERO() {
315 VM_VERIFY_SIZE(1)
316 VM_PARAM_FLOAT(aero)
318 valid_agent(targ);
319 targ->aero = aero;
323 AERO (float)
324 %status maybe
326 Returns the aerodynamics of the TARG agent.
328 void caosVM::v_AERO() {
329 VM_VERIFY_SIZE(0)
331 valid_agent(targ);
332 result.setFloat(targ->aero.getFloat());
336 AERO (variable)
337 %status maybe
338 %pragma variants c2
339 %pragma implementation caosVM::v_AERO_c2
340 %pragma saveimpl caosVM::s_AERO_c2
342 Returns the aerodynamics of the TARG agent.
344 CAOS_LVALUE_TARG_SIMPLE(AERO_c2, targ->aero)
347 RELX (float) first (agent) second (agent)
348 %status maybe
350 Returns the relative horizontal distance between the centers of the two given agents.
352 void caosVM::v_RELX() {
353 VM_VERIFY_SIZE(2)
354 VM_PARAM_VALIDAGENT(second)
355 VM_PARAM_VALIDAGENT(first)
357 float one = first->x + (first->getWidth() / 2.0);
358 float two = second->x + (second->getWidth() / 2.0);
360 result.setFloat(two - one);
364 RELY (float) first (agent) second (agent)
365 %status maybe
367 Returns the relative vertical distance between the centers of the two given agents.
369 void caosVM::v_RELY() {
370 VM_VERIFY_SIZE(2)
371 VM_PARAM_VALIDAGENT(second)
372 VM_PARAM_VALIDAGENT(first)
374 float one = first->y + (first->getHeight() / 2.0);
375 float two = second->y + (second->getHeight() / 2.0);
377 result.setFloat(two - one);
381 RELX (integer)
382 %status maybe
383 %pragma variants c2
384 %pragma implementation caosVM::v_RELX_c2
386 Returns the relative horizontal distance between the script owner and the target agent.
388 void caosVM::v_RELX_c2() {
389 valid_agent(targ);
390 valid_agent(owner);
392 // TODO: correct?
393 result.setInt((int)targ->x + (targ->getWidth() / 2) - ((int)owner->x + (owner->getWidth() / 2)));
397 RELY (integer)
398 %status maybe
399 %pragma variants c2
400 %pragma implementation caosVM::v_RELY_c2
402 Returns the relative vertical distance between the script owner and the target agent.
404 void caosVM::v_RELY_c2() {
405 valid_agent(targ);
406 valid_agent(owner);
408 // TODO: correct?
409 result.setInt((int)targ->y + (targ->getHeight() / 2) - ((int)owner->y + (owner->getHeight() / 2)));
413 VELO (command) xvel (float) yvel (float)
414 %status maybe
416 Sets the horizontal and vertical velocity of the TARG agent, in pixels/tick.
418 void caosVM::c_VELO() {
419 VM_VERIFY_SIZE(2)
420 VM_PARAM_FLOAT(vely)
421 VM_PARAM_FLOAT(velx)
423 valid_agent(targ);
424 targ->velx.reset();
425 targ->velx.setFloat(velx);
426 targ->vely.reset();
427 targ->vely.setFloat(vely);
431 MVSF (command) x (float) y (float)
432 %status maybe
434 Move the target agent to an area inside the room system at about (x, y).
435 This allows 'safe' moves.
437 void caosVM::c_MVSF() {
438 VM_PARAM_FLOAT(y)
439 VM_PARAM_FLOAT(x)
440 valid_agent(targ);
442 if (!targ->tryMoveToPlaceAround(x, y))
443 throw creaturesException(boost::str(boost::format("MVSF failed to find a safe place around (%d, %d)") % x % y));
447 FRIC (float)
448 %status maybe
450 Returns the TARG agent's coefficient of friction as a percentage.
452 void caosVM::v_FRIC() {
453 VM_VERIFY_SIZE(0)
455 valid_agent(targ);
456 result.setFloat(targ->friction);
460 FRIC (command) friction (integer)
461 %status maybe
463 Sets the TARG agent's coefficient of friction, or the percentage of motion that will be lost as it slides on a
464 surface.
466 void caosVM::c_FRIC() {
467 VM_VERIFY_SIZE(1)
468 VM_PARAM_INTEGER(friction) caos_assert(friction >= 0); caos_assert(friction <= 100);
470 valid_agent(targ);
471 targ->friction = friction;
475 FALL (integer)
476 %status maybe
478 Returns 1 if the TARG agent is moving due to gravity, or 0 if otherwise.
480 void caosVM::v_FALL() {
481 VM_VERIFY_SIZE(0)
482 valid_agent(targ);
484 // XXX: this probably isn't quite correct, but it's close enough for now.
485 if (targ->falling)
486 result.setInt(1);
487 else
488 result.setInt(0);
492 MOVS (variable)
493 %status maybe
494 %pragma variants c1 c2 cv c3 sm
496 Returns an integer representing the motion status of the TARG agent. 0 is autonomous, 1 is moving by mouse, 2 is
497 floating, 3 is inside a vehicle, and 4 is being carried.
499 void caosVM::v_MOVS() {
500 // TODO: check these values match c1
502 valid_agent(targ);
504 caosVar r;
506 // TODO: agents can possibly have multiple MOVS states right now, we should make sure to avoid that
507 if (targ->carriedby) {
508 if (targ->carriedby.get() == (Agent *)world.hand())
509 r = 1;
510 else
511 r = 4;
512 } else if (targ->invehicle)
513 r = 3;
514 else if (targ->floatable()) // TODO: good?
515 r = 2;
516 else
517 r = 0;
519 valueStack.push_back(r);
521 void caosVM::s_MOVS() {
522 VM_PARAM_VALUE(newvalue)
523 caos_assert(newvalue.hasInt());
524 valid_agent(targ);
526 // TODO: implement MOVS setting
530 FLTO (command) x (float) y (float)
531 %status maybe
533 Sets the TARG agent to float its top-left corner (x, y) away from the top-left corner of the FREL agent.
535 void caosVM::c_FLTO() {
536 VM_PARAM_FLOAT(y)
537 VM_PARAM_FLOAT(x)
539 valid_agent(targ);
540 targ->floatTo(x, y);
544 FREL (command) agent (agent)
545 %status maybe
547 Sets the agent the TARG agent floats relative to. You must set the 'floatable' attribute for this to work.
548 The default is NULL, which means the target agent floats relative to the main camera.
550 void caosVM::c_FREL() {
551 VM_PARAM_AGENT(agent)
553 valid_agent(targ);
554 targ->floatTo(agent);
558 FLTX (float)
559 %status maybe
561 Returns the x value of the TARG agent's floating vector.
563 void caosVM::v_FLTX() {
564 valid_agent(targ);
566 if (targ->floatingagent)
567 result.setFloat(targ->floatingagent->x - targ->x);
568 else
569 result.setFloat(world.camera.getX() - targ->x);
573 FLTY (float)
574 %status maybe
576 Returns the y value of the TARG agent's floating vector.
578 void caosVM::v_FLTY() {
579 valid_agent(targ);
581 if (targ->floatingagent)
582 result.setFloat(targ->floatingagent->x - targ->x);
583 else
584 result.setFloat(world.camera.getX() - targ->x);
588 MCRT (command) x (integer) y (integer)
589 %status stub
590 %pragma variants c1 c2
592 Remove limits from target object and move it to (x, y).
594 void caosVM::c_MCRT() {
595 c_MVTO(); // TODO
599 REST (variable)
600 %status maybe
601 %pragma variants c2
603 CAOS_LVALUE_TARG_SIMPLE(REST, targ->rest)
605 /* vim: set noet: */