check activateable() before allowing clicks (oops)
[openc2e.git] / caosVM_agent.cpp
blobc86c06810ef2fb533b37ef9428b23edad38ce5ae
1 /*
2 * caosVM_agent.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Sun May 30 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 "Vehicle.h"
23 #include "Blackboard.h"
24 #include "PointerAgent.h"
25 #include "SkeletalCreature.h"
26 #include "World.h"
27 #include "creaturesImage.h"
28 #include <iostream>
29 #include <boost/format.hpp>
30 #include "AgentHelpers.h"
31 #include "Room.h" // LIML/LIMT etc
33 using std::cerr;
35 AnimatablePart *caosVM::getCurrentAnimatablePart() {
36 valid_agent(targ);
37 CompoundPart *p = targ->part(part);
38 if (!p) return 0;
39 AnimatablePart *s = dynamic_cast<AnimatablePart *>(p);
40 return s;
43 SpritePart *caosVM::getCurrentSpritePart() {
44 valid_agent(targ);
45 CompoundPart *p = targ->part(part);
46 if (!p) return 0;
47 SpritePart *s = dynamic_cast<SpritePart *>(p);
48 return s;
51 /**
52 TOUC (integer) first (agent) second (agent)
53 %status maybe
54 %pragma variants c1 c2 cv c3 sm
55 %cost c1,c2 0
57 Determines whether the two given agents are touching. Returns 0 (if not) or 1 (if so).
59 void caosVM::v_TOUC() {
60 VM_VERIFY_SIZE(2)
61 VM_PARAM_AGENT(second)
62 VM_PARAM_AGENT(first)
64 if (first && second && agentsTouching(first.get(), second.get()))
65 result.setInt(1);
66 else
67 result.setInt(0);
70 /**
71 RTAR (command) family (integer) genus (integer) species (integer)
72 %status maybe
73 %pragma variants c1 c2 cv c3 sm
74 %cost c1,c2 0
76 Sets TARG to a random agent with the given family/genus/species.
77 */
78 void caosVM::c_RTAR() {
79 VM_VERIFY_SIZE(3)
80 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
81 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
82 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
84 setTarg(0);
86 /* XXX: maybe use a map of classifier -> agents? */
87 std::vector<boost::shared_ptr<Agent> > temp;
88 for (std::list<boost::shared_ptr<Agent> >::iterator i
89 = world.agents.begin(); i != world.agents.end(); i++) {
91 Agent *a = i->get();
92 if (!a) continue;
94 if (species && species != a->species) continue;
95 if (genus && genus != a->genus) continue;
96 if (family && family != a->family) continue;
98 temp.push_back(*i);
101 if (temp.size() == 0) return;
102 int i = rand() % temp.size(); // TODO: better randomness
103 setTarg(temp[i]);
107 TTAR (command) family (integer) genus (integer) species (integer)
108 %status maybe
110 Locates a random agent that is touching OWNR (see ETCH) and that
111 matches the given classifier, and sets it to TARG.
113 void caosVM::c_TTAR() {
114 VM_VERIFY_SIZE(3)
115 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
116 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
117 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
119 valid_agent(owner);
121 setTarg(0);
123 /* XXX: maybe use a map of classifier -> agents? */
124 std::vector<boost::shared_ptr<Agent> > temp;
125 for (std::list<boost::shared_ptr<Agent> >::iterator i
126 = world.agents.begin(); i != world.agents.end(); i++) {
128 Agent *a = i->get();
129 if (!a) continue;
131 if (species && species != a->species) continue;
132 if (genus && genus != a->genus) continue;
133 if (family && family != a->family) continue;
135 if (agentsTouching(owner, a))
136 temp.push_back(*i);
139 if (temp.size() == 0) return;
140 int i = rand() % temp.size(); // TODO: better randomness
141 setTarg(temp[i]);
145 STAR (command) family (integer) genus (integer) species (integer)
146 %status maybe
147 %pragma variants c2 cv c3 sm
149 Locates a random agent that is visible to OWNR (see ESEE) and that
150 matches the given classifier, then sets it to TARG.
152 void caosVM::c_STAR() {
153 VM_VERIFY_SIZE(3)
154 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
155 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
156 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
158 valid_agent(targ);
160 Agent *seeing;
161 if (owner) seeing = owner; else seeing = targ;
162 valid_agent(seeing);
164 std::vector<boost::shared_ptr<Agent> > agents = getVisibleList(seeing, family, genus, species);
165 if (agents.size() == 0) {
166 setTarg(0);
167 } else {
168 unsigned int i = (int) (agents.size() * (rand() / (RAND_MAX + 1.0)));
169 setTarg(agents[i]);
174 NEW: SIMP (command) family (integer) genus (integer) species (integer) sprite_file (string) image_count (integer) first_image (integer) plane (integer)
175 %status maybe
177 Creates a new simple agent with given family/genus/species, given spritefile with image_count sprites
178 available starting at first_image in the spritefile, at the screen depth given by plane.
179 TARG is set to the newly-created agent.
181 void caosVM::c_NEW_SIMP() {
182 VM_VERIFY_SIZE(7)
183 VM_PARAM_INTEGER(plane)
184 VM_PARAM_INTEGER(first_image)
185 VM_PARAM_INTEGER(image_count)
186 VM_PARAM_STRING(sprite_file)
187 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
188 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
189 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
191 SimpleAgent *a = new SimpleAgent(family, genus, species, plane, sprite_file, first_image, image_count);
192 a->finishInit();
193 setTarg(a);
194 part = 0; // TODO: correct?
198 NEW: SIMP (command) sprite_file (bareword) image_count (integer) first_image (integer) plane (integer) clone (integer)
199 %status maybe
200 %pragma variants c1 c2
201 %cost c1,c2 1
202 %pragma implementation caosVM::c_NEW_SIMP_c2
204 void caosVM::c_NEW_SIMP_c2() {
205 VM_PARAM_INTEGER(clone)
206 VM_PARAM_INTEGER(plane)
207 VM_PARAM_INTEGER(first_image)
208 VM_PARAM_INTEGER(image_count)
209 VM_PARAM_STRING(sprite_file)
211 // TODO: we ignore clone
212 // TODO: should we init with 0/0/0 or with a different constructor?
213 SimpleAgent *a = new SimpleAgent(0, 0, 0, plane, sprite_file, first_image, image_count);
214 a->finishInit();
215 setTarg(a);
216 part = 0; // TODO: correct?
220 NEW: COMP (command) family (integer) genus (integer) species (integer) sprite_file (string) image_count (integer) first_image (integer) plane (integer)
221 %status maybe
223 Creates a new composite agent with given family/genus/species, given spritefile with image_count sprites
224 available starting at first_image in the spritefile, with the first part at the screen depth given by plane.
226 void caosVM::c_NEW_COMP() {
227 VM_VERIFY_SIZE(7)
228 VM_PARAM_INTEGER(plane)
229 VM_PARAM_INTEGER(first_image)
230 VM_PARAM_INTEGER(image_count)
231 VM_PARAM_STRING(sprite_file)
232 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
233 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
234 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
236 CompoundAgent *a = new CompoundAgent(family, genus, species, plane, sprite_file, first_image, image_count);
237 a->finishInit();
238 setTarg(a);
239 part = 0; // TODO: correct?
243 NEW: COMP (command) sprite_file (bareword) image_count (integer) first_image (integer) clone (integer)
244 %status maybe
245 %pragma variants c1 c2
246 %pragma implementation caosVM::c_NEW_COMP_c1
248 void caosVM::c_NEW_COMP_c1() {
249 VM_PARAM_INTEGER(clone)
250 VM_PARAM_INTEGER(first_image)
251 VM_PARAM_INTEGER(image_count)
252 VM_PARAM_STRING(sprite_file)
254 // TODO: what does clone do?
255 CompoundAgent *a = new CompoundAgent(sprite_file, first_image, image_count);
256 a->finishInit();
257 setTarg(a);
258 // TODO: should part be set here?
262 NEW: VHCL (command) family (integer) genus (integer) species (integer) sprite_file (string) image_count (integer) first_image (integer) plane (integer)
263 %status maybe
265 Creates a new vehicle agent with given family/genus/species, given spritefile with image_count sprites
266 available starting at first_image in the spritefile, with the first part at the screen depth given by plane.
268 void caosVM::c_NEW_VHCL() {
269 VM_VERIFY_SIZE(7)
270 VM_PARAM_INTEGER(plane)
271 VM_PARAM_INTEGER(first_image)
272 VM_PARAM_INTEGER(image_count)
273 VM_PARAM_STRING(sprite_file)
274 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
275 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
276 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
278 Vehicle *a = new Vehicle(family, genus, species, plane, sprite_file, first_image, image_count);
279 a->finishInit();
280 setTarg(a);
281 part = 0; // TODO: correct?
285 NEW: VHCL (command) sprite_file (bareword) image_count (integer) first_image (integer)
286 %status maybe
287 %pragma variants c1 c2
288 %pragma implementation caosVM::c_NEW_VHCL_c1
290 void caosVM::c_NEW_VHCL_c1() {
291 VM_PARAM_INTEGER(first_image)
292 VM_PARAM_INTEGER(image_count)
293 VM_PARAM_STRING(sprite_file)
295 Vehicle *a = new Vehicle(sprite_file, first_image, image_count);
296 a->finishInit();
297 setTarg(a);
298 // TODO: should part be set here?
302 NEW: BKBD (command) sprite_file (bareword) image_count (integer) first_image (integer) background_colour (integer) chalk_colour (integer) alias_colour (integer) textx (integer) texty (integer)
303 %status maybe
304 %pragma variants c1 c2
306 void caosVM::c_NEW_BKBD() {
307 VM_PARAM_INTEGER(texty)
308 VM_PARAM_INTEGER(textx)
309 VM_PARAM_INTEGER(alias_colour)
310 VM_PARAM_INTEGER(chalk_colour)
311 VM_PARAM_INTEGER(background_colour)
312 VM_PARAM_INTEGER(first_image)
313 VM_PARAM_INTEGER(image_count)
314 VM_PARAM_STRING(sprite_file)
316 Blackboard *a = new Blackboard(sprite_file, first_image, image_count);
317 a->finishInit();
318 setTarg(a);
320 // TODO: actually initialise blackboard parameters
324 NEW: CBUB (command) sprite_file (bareword) image_count (integer) first_image (integer) stringid (integer)
325 %status maybe
326 %pragma variants c2
328 void caosVM::c_NEW_CBUB() {
329 VM_PARAM_INTEGER(stringid)
330 VM_PARAM_INTEGER(first_image)
331 VM_PARAM_INTEGER(image_count)
332 VM_PARAM_STRING(sprite_file)
334 throw creaturesException("compound bubble objects are not supported yet"); // TODO
338 TARG (agent)
339 %status maybe
340 %pragma variants c1 c2 cv c3 sm
342 Returns TARG, the currently-targeted agent.
344 void caosVM::v_TARG() {
345 VM_VERIFY_SIZE(0)
346 result.setAgent(targ);
350 OWNR (agent)
351 %status maybe
352 %pragma variants c1 c2 cv c3 sm
353 %cost c1,c2 0
355 Returns OWNR, the agent that is running the script.
357 void caosVM::v_OWNR() {
358 VM_VERIFY_SIZE(0)
359 result.setAgent(owner);
363 NULL (agent)
364 %status maybe
366 Returns a null (zero) agent.
368 void caosVM::v_NULL() {
369 static const AgentRef nullref;
370 VM_VERIFY_SIZE(0)
371 result.setAgent(nullref);
375 POSE (command) pose (integer)
376 %status maybe
377 %pragma variants c1 c2 cv c3 sm
378 %cost c1,c2 1
380 Sets the displayed sprite of TARG to the frame in the sprite file with the given integer.
382 void caosVM::c_POSE() {
383 VM_VERIFY_SIZE(1)
384 VM_PARAM_INTEGER(pose)
386 AnimatablePart *p = getCurrentAnimatablePart();
387 caos_assert(p);
389 SpritePart *s = dynamic_cast<SpritePart *>(p);
390 if (s)
391 caos_assert(s->getFirstImg() + s->getBase() + pose < s->getSprite()->numframes());
393 p->setPose(pose);
397 ATTR (command) attr (integer)
398 %status maybe
400 Sets attributes of the TARG agent.
402 void caosVM::c_ATTR() {
403 VM_VERIFY_SIZE(1)
404 VM_PARAM_INTEGER(attr)
405 valid_agent(targ);
407 bool oldfloat = targ->floatable();
408 targ->setAttributes(attr);
410 // TODO: this is an icky hack to enable floating, we should write correct floating
411 // behaviour so we don't need to maintain floating lists like this :/
412 if (oldfloat != targ->floatable()) {
413 if (targ->floatable())
414 targ->floatSetup();
415 else
416 targ->floatRelease();
421 ATTR (variable)
422 %status maybe
423 %pragma variants c1 c2 cv c3 sm
425 Attributes of the TARG agent.
427 CAOS_LVALUE_TARG_SIMPLE(ATTR, targ->attr);
430 TICK (command) tickrate (integer)
431 %status maybe
432 %pragma variants c1 c2 cv c3 sm
433 %cost c1,c2 0
435 Initiates the agent timer-- the Timer script will then be run once every tickrate ticks.
436 Setting tickrate to zero will stop the timer.
438 void caosVM::c_TICK() {
439 VM_VERIFY_SIZE(1)
440 VM_PARAM_INTEGER(tickrate)
441 valid_agent(targ);
442 targ->setTimerRate(tickrate);
446 BHVR (command) bhvr (integer)
447 %status maybe
449 Sets the behaviour of the TARG agent.
451 void caosVM::c_BHVR() {
452 VM_VERIFY_SIZE(1)
453 VM_PARAM_INTEGER(bhvr)
455 valid_agent(targ);
457 // reset bhvr
458 targ->cr_can_push = targ->cr_can_pull = targ->cr_can_stop =
459 targ->cr_can_hit = targ->cr_can_eat = targ->cr_can_pickup = false;
461 if (bhvr & 0x1) // creature can push
462 targ->cr_can_push = true;
463 if (bhvr & 0x2) // creature can pull
464 targ->cr_can_pull = true;
465 if (bhvr & 0x4) // creature can stop
466 targ->cr_can_stop = true;
467 if (bhvr & 0x8) // creature can hit
468 targ->cr_can_hit = true;
469 if (bhvr & 0x10) // creature can eat
470 targ->cr_can_eat = true;
471 if (bhvr & 0x20) // creature can pick up
472 targ->cr_can_pickup = true;
476 TARG (command) agent (agent)
477 %status maybe
478 %pragma variants c1 c2 cv c3 sm
479 %cost c1,c2 0
481 Sets TARG (the target agent) to the given agent.
483 void caosVM::c_TARG() {
484 VM_VERIFY_SIZE(1)
485 VM_PARAM_AGENT(a)
486 setTarg(a);
490 FROM (agent)
491 %status maybe
492 %pragma variants c1 c2 cv sm
494 Returns the agent that sent the message being processed, or NULL if no agent was involved.
496 void caosVM::v_FROM() {
497 result.setAgent(from.getAgent());
501 FROM (variable)
502 %status maybe
503 %pragma variants c3
504 %pragma implementation caosVM::v_FROM_ds
506 Returns the agent that sent the message being processed, or NULL if no agent was involved.
508 // Returns a variable because DS is insane and uses this for network events too (and so, of course, scripts abuse it).
509 CAOS_LVALUE_SIMPLE(FROM_ds, from);
512 POSE (integer)
513 %status maybe
514 %pragma variants c1 c2 cv c3 sm
516 Returns the number of the frame in the TARG part/agent's sprite file that is currently being displayed, or -1 if part# doesn't exist on a compound agent.
518 void caosVM::v_POSE() {
519 VM_VERIFY_SIZE(0)
521 valid_agent(targ);
523 SpritePart *p = getCurrentSpritePart();
524 if (p)
525 result.setInt(p->getPose());
526 else
527 result.setInt(-1);
531 KILL (command) agent (agent)
532 %status maybe
533 %pragma variants c1 c2 cv c3 sm
534 %cost c1,c2 1
536 Destroys the agent in question. However, you cannot destroy PNTR.
537 Remember, use DEAD first for Creatures!
539 void caosVM::c_KILL() {
540 VM_VERIFY_SIZE(1)
541 VM_PARAM_VALIDAGENT(a)
543 // note that kill is a virtual function which doesn't work on PNTR
544 a->kill();
548 ANIM (command) poselist (bytestring)
549 %status maybe
551 Sets the animation string for TARG, in the format '1 2 3 4'.
552 If it ends with '255', loops back to beginning; if it ends with '255 X', loops back to frame X.
554 <i>todo: compound agent stuff</i>
556 void caosVM::c_ANIM() {
557 VM_VERIFY_SIZE(1)
558 VM_PARAM_BYTESTR(bs)
560 valid_agent(targ);
562 AnimatablePart *p = getCurrentAnimatablePart();
563 caos_assert(p);
564 p->animation = bs;
566 if (!bs.empty()) p->setFrameNo(0); // TODO: correct?
570 ANIM (command) animstring (string)
571 %status maybe
572 %pragma variants c1 c2
573 %pragma implementation caosVM::c_ANIM_c2
574 %cost c1,c2 1
576 Sets the animation string for TARG, in the format '1234'.
577 If it ends with 'R', loops back to the beginning.
579 void caosVM::c_ANIM_c2() {
580 VM_PARAM_STRING(animstring)
582 valid_agent(targ);
584 // TODO: support creatures (using AnimatablePart, see c2e ANIM) for this (with format like "001002003R")
585 if (dynamic_cast<SkeletalCreature *>(targ.get())) return;
587 SpritePart *p = getCurrentSpritePart();
588 caos_assert(p);
590 p->animation.clear();
592 for (unsigned int i = 0; i < animstring.size(); i++) {
593 if (animstring[i] == 'R') {
594 p->animation.push_back(255);
595 } else if (animstring[i] >= 48 && animstring[i] <= 57) {
596 p->animation.push_back(animstring[i] - 48);
597 } else if (animstring[i] >= 97 && animstring[i] <= 122) {
598 // TODO: c1 grendel eggs have 'a' at the end of their animation strings, this is an untested attempt to handle that
599 p->animation.push_back(animstring[i] - 97);
600 } else {
601 p->animation.clear();
602 throw creaturesException(std::string("old-style animation string contained '") + animstring[i] + "', which we didn't understand");
606 if (!animstring.empty()) p->setFrameNo(0); // TODO: correct?
610 ANMS (command) poselist (string)
611 %status maybe
613 Exactly like ANIM, only using a string and not a bytestring for poselist source.
615 void caosVM::c_ANMS() {
616 VM_PARAM_STRING(poselist)
618 // TODO: technically, we should parse this properly, also do error checking
619 bytestring_t animation;
621 std::string t;
622 for (unsigned int i = 0; i < poselist.size(); i++) {
623 if (poselist[i] == ' ')
624 if (!t.empty()) {
625 int n = atoi(t.c_str());
626 caos_assert(n >= 0 && n < 256);
627 animation.push_back(n);
629 else
630 t = t + poselist[i];
633 AnimatablePart *p = getCurrentAnimatablePart();
634 caos_assert(p);
635 p->animation = animation;
637 if (!animation.empty()) p->setFrameNo(0); // TODO: correct?
641 ABBA (integer)
642 %status maybe
644 Returns the first_image (ie, absolute base) value for the current agent/part, or -1 if part# doesn't exist on a compound agent.
646 void caosVM::v_ABBA() {
647 VM_VERIFY_SIZE(0)
649 SpritePart *p = getCurrentSpritePart();
650 if (p)
651 result.setInt(p->getFirstImg());
652 else
653 result.setInt(-1);
657 BASE (command) index (integer)
658 %status maybe
659 %pragma variants c1 c2 cv c3 sm
660 %cost c1,c2 0
662 Sets the frame in the TARG agent's spritefile that will be used as its base image.
663 This is relative to the first image set with one of the NEW: commands.
665 void caosVM::c_BASE() {
666 VM_VERIFY_SIZE(1)
667 VM_PARAM_INTEGER(index)
669 valid_agent(targ);
671 SpritePart *p = getCurrentSpritePart();
672 caos_assert(p);
673 // Note that we don't check validity here because a lot of code changes BASE and then only afterwards POSE/ANIM.
674 p->setBase(index);
678 BASE (integer)
679 %status maybe
681 Returns the frame in the TARG agent/part's spritefile being used as the BASE image, or -1 if part# doesn't exist on a compound agent.
683 void caosVM::v_BASE() {
684 VM_VERIFY_SIZE(0)
686 SpritePart *p = getCurrentSpritePart();
687 if (p)
688 result.setInt(p->getBase());
689 else
690 result.setInt(-1);
694 BHVR (integer)
695 %status maybe
697 Returns the behaviour of the TARG agent.
699 void caosVM::v_BHVR() {
700 VM_VERIFY_SIZE(0)
702 valid_agent(targ);
704 unsigned char bvr = 0;
706 if (targ->cr_can_push) bvr += 0x1;
707 if (targ->cr_can_pull) bvr += 0x2;
708 if (targ->cr_can_stop) bvr += 0x4;
709 if (targ->cr_can_hit) bvr += 0x8;
710 if (targ->cr_can_eat) bvr += 0x10;
711 if (targ->cr_can_pickup) bvr += 0x20;
713 result.setInt(bvr);
717 CARR (agent)
718 %status maybe
720 Returns the agent that is carrying the TARG agent. If TARG is not being carried, returns
721 NULL.
723 void caosVM::v_CARR() {
724 VM_VERIFY_SIZE(0)
725 valid_agent(targ);
727 // TODO: muh, should totally be virtual
728 if (targ->invehicle)
729 result.setAgent(targ->invehicle);
730 else
731 result.setAgent(targ->carriedby);
735 CARR (agent)
736 %status maybe
737 %pragma variants c1 c2
738 %pragma implementation caosVM::v_CARR_c1
740 Returns the agent that is carrying the OWNR agent. If OWNR is not being carried, returns
741 NULL.
743 void caosVM::v_CARR_c1() {
744 VM_VERIFY_SIZE(0)
745 valid_agent(owner);
747 result.setAgent(owner->carriedby);
751 FMLY (integer)
752 %status maybe
753 %pragma variants c1 c2 cv c3 sm
755 Returns the family of the TARG agent.
757 void caosVM::v_FMLY() {
758 VM_VERIFY_SIZE(0)
759 valid_agent(targ);
760 result.setInt(targ->family);
764 GNUS (integer)
765 %status maybe
766 %pragma variants c1 c2 cv c3 sm
768 Returns the genus of the TARG agent.
770 void caosVM::v_GNUS() {
771 VM_VERIFY_SIZE(0)
772 valid_agent(targ);
773 result.setInt(targ->genus);
777 SPCS (integer)
778 %status maybe
779 %pragma variants c1 c2 cv c3 sm
781 Returns the species of the TARG agent.
783 void caosVM::v_SPCS() {
784 VM_VERIFY_SIZE(0)
785 valid_agent(targ);
786 result.setInt(targ->species);
790 PLNE (integer)
791 %status maybe
793 Returns the plane (z-order) of the TARG agent.
795 void caosVM::v_PLNE() {
796 VM_VERIFY_SIZE(0)
797 valid_agent(targ);
798 result.setInt(targ->getZOrder());
802 PNTR (agent)
803 %status maybe
804 %pragma variants c1 c2 cv c3 sm
806 Returns the pointer agent (the Hand).
808 void caosVM::v_PNTR() {
809 VM_VERIFY_SIZE(0)
810 result.setAgent(world.hand());
813 #include "Engine.h" // for engine.version check, sigh
814 unsigned int calculateScriptId(unsigned int message_id) {
815 // aka, why oh why is this needed? Silly CL.
817 switch (message_id) {
818 case 2: /* deactivate */
819 return 0;
820 case 8: /* hilarious special case to fix c2 airlock */
821 if (engine.version < 3)
822 return 7;
823 else
824 return 8;
825 case 0: /* activate 1 */
826 case 1: /* activate 2 */
827 return message_id + 1;
830 return message_id;
834 MESG WRIT (command) agent (agent) message_id (integer)
835 %status maybe
836 %pragma variants c1 c2 cv c3 sm
837 %cost c1,c2 0
839 Sends a message of type message_id to the given agent. FROM will be set to OWNR unless
840 there is no agent involved in sending the message.
842 void caosVM::c_MESG_WRIT() {
843 VM_VERIFY_SIZE(2)
844 VM_PARAM_INTEGER(message_id)
845 VM_PARAM_VALIDAGENT(agent);
847 agent->queueScript(calculateScriptId(message_id), owner.get());
851 MESG WRT+ (command) agent (agent) message_id (integer) param_1 (anything) param_2 (anything) delay (integer)
852 %status maybe
853 %pragma variants c2 cv c3 sm
855 Sends a message of type message_id to the given agent, much like MESG WRIT, but with the
856 addition of parameters. The message will be sent after waiting the number of ticks set
857 in delay (except doesn't, right now. Delay must be set to zero for now.)
859 void caosVM::c_MESG_WRT() {
860 VM_VERIFY_SIZE(5)
861 VM_PARAM_INTEGER(delay)
862 VM_PARAM_VALUE(param_2)
863 VM_PARAM_VALUE(param_1)
864 VM_PARAM_INTEGER(message_id)
865 VM_PARAM_VALIDAGENT(agent)
867 // I'm not sure how to handle the 'delay'; is it a background delay, or do we actually block for delay ticks?
868 // TODO: fuzzie can't work out how on earth delays work in c2e, someone fixit
870 agent->queueScript(calculateScriptId(message_id), owner.get(), param_1, param_2);
874 TOTL (integer) family (integer) genus (integer) species (integer)
875 %status maybe
876 %pragma variants c1 c2 cv c3 sm
878 Returns the total number of in-game agents matching the given family/genus/species.
880 void caosVM::v_TOTL() {
881 VM_VERIFY_SIZE(3)
882 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
883 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
884 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
886 unsigned int x = 0;
887 for (std::list<boost::shared_ptr<Agent> >::iterator i = world.agents.begin(); i != world.agents.end(); i++) {
888 if (!*i) continue;
889 if ((*i)->family == family || family == 0)
890 if ((*i)->genus == genus || genus == 0)
891 if ((*i)->species == species || species == 0)
892 x++;
894 result.setInt(x);
898 SHOW (command) visibility (integer)
899 %status maybe
901 Sets visibility of the TARG agent to cameras. 0 = invisible, 1 = visible.
903 void caosVM::c_SHOW() {
904 VM_VERIFY_SIZE(1)
905 VM_PARAM_INTEGER(visibility)
906 caos_assert((visibility == 0) || (visibility == 1));
907 valid_agent(targ);
908 targ->visible = visibility;
912 SHOW (integer)
913 %status maybe
915 void caosVM::v_SHOW() {
916 valid_agent(targ);
917 result.setInt(targ->visible ? 1 : 0);
921 POSX (float)
922 %status maybe
923 %pragma variants c2 cv c3 sm
925 Returns the X position of the TARG agent in the world.
927 void caosVM::v_POSX() {
928 VM_VERIFY_SIZE(0)
929 valid_agent(targ);
930 result.setFloat(targ->x + (targ->getWidth() / 2.0f));
934 POSY (float)
935 %status maybe
936 %pragma variants c2 cv c3 sm
938 Returns the Y position of the TARG agent in the world.
940 void caosVM::v_POSY() {
941 VM_VERIFY_SIZE(0)
942 valid_agent(targ);
943 result.setFloat(targ->y + (targ->getHeight() / 2.0f));
947 FRAT (command) framerate (integer)
948 %status maybe
950 Sets the delay between frame changes of the TARG agent or current PART.
951 Must be from 1 to 255, 1 being the normal rate, 2 being half as quickly, and so on.
953 void caosVM::c_FRAT() {
954 VM_VERIFY_SIZE(1)
955 VM_PARAM_INTEGER(framerate)
957 caos_assert(framerate >= 1 && framerate <= 255);
958 valid_agent(targ);
960 SpritePart *p = getCurrentSpritePart();
961 caos_assert(p);
962 p->setFramerate(framerate);
963 p->framedelay = 0;
966 class blockUntilOver : public blockCond {
967 protected:
968 AgentRef targ;
969 int part;
970 public:
971 blockUntilOver(Agent *t, int p) : targ(t), part(p) {}
972 virtual bool operator()() {
973 bool blocking;
974 int fno, animsize;
976 if (!targ) return false;
978 CompoundPart *s = targ->part(part);
979 caos_assert(s);
980 AnimatablePart *p = dynamic_cast<AnimatablePart *>(s);
981 caos_assert(p);
983 fno = p->getFrameNo();
984 animsize = p->animation.size();
986 if (fno + 1 == animsize) blocking = false;
987 else if (animsize == 0) blocking = false;
988 else blocking = true;
989 return blocking;
995 OVER (command)
996 %status maybe
997 %pragma variants c1 c2 cv c3 sm
999 Waits (blocks the TARG agent) until the animation of the TARG agent or PART is over.
1001 void caosVM::c_OVER() {
1002 valid_agent(targ);
1004 // TODO: The Burrows uses OVER in install script, so fuzzie's making this optional for now, but is this right?
1005 if (owner)
1006 startBlocking(new blockUntilOver(targ, part));
1010 PUHL (command) pose (integer) x (integer) y (integer)
1011 %status maybe
1013 Sets relative x/y coordinates for TARG's pickup point.
1014 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1016 void caosVM::c_PUHL() {
1017 VM_VERIFY_SIZE(3)
1018 VM_PARAM_INTEGER(y)
1019 VM_PARAM_INTEGER(x)
1020 VM_PARAM_INTEGER(pose)
1022 valid_agent(targ);
1024 if (pose == -1) {
1025 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1026 if (s) {
1027 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1028 targ->carried_points[i] = std::pair<int, int>(x, y);
1030 } else {
1031 // ..Assume a single pose for non-sprite parts.
1032 targ->carried_points[0] = std::pair<int, int>(x, y);
1034 } else {
1035 targ->carried_points[pose] = std::pair<int, int>(x, y);
1040 SETV PUHL (command) pose (integer) x (integer) y (integer)
1041 %status maybe
1042 %pragma variants c2
1044 Sets relative x/y coordinates for TARG's pickup point.
1045 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1047 void caosVM::c_SETV_PUHL() {
1048 c_PUHL();
1052 PUHL (integer) pose (integer) x_or_y (integer)
1053 %status maybe
1055 Returns the coordinate for TARG's pickup point. x_or_y should be 1 for x, or 2 for y.
1057 void caosVM::v_PUHL() {
1058 VM_PARAM_INTEGER(x_or_y)
1059 VM_PARAM_INTEGER(pose)
1061 valid_agent(targ);
1063 // TODO: this creates the variable if it doesn't exist yet, correct behaviour?
1064 if (x_or_y == 1) {
1065 result.setInt(targ->carried_points[pose].first);
1066 } else {
1067 caos_assert(x_or_y == 2);
1068 result.setInt(targ->carried_points[pose].second);
1073 POSL (float)
1074 %status maybe
1075 %pragma variants c1 c2 cv c3 sm
1077 Returns the position of the left side of TARG's bounding box.
1079 void caosVM::v_POSL() {
1080 VM_VERIFY_SIZE(0)
1082 valid_agent(targ);
1083 result.setFloat(targ->x);
1087 POST (float)
1088 %status maybe
1089 %pragma variants c1 c2 cv c3 sm
1091 Returns the position of the top side of TARG's bounding box.
1093 void caosVM::v_POST() {
1094 VM_VERIFY_SIZE(0)
1096 valid_agent(targ);
1097 result.setFloat(targ->y);
1101 POSR (float)
1102 %status maybe
1103 %pragma variants c1 c2 cv c3 sm
1105 Returns the position of the right side of TARG's bounding box.
1107 void caosVM::v_POSR() {
1108 VM_VERIFY_SIZE(0)
1110 valid_agent(targ);
1111 result.setFloat(targ->x + targ->getWidth());
1115 POSB (float)
1116 %status maybe
1117 %pragma variants c1 c2 cv c3 sm
1119 Returns the position of the bottom side of TARG's bounding box.
1121 void caosVM::v_POSB() {
1122 VM_VERIFY_SIZE(0)
1124 valid_agent(targ);
1125 result.setFloat(targ->y + targ->getHeight());
1129 WDTH (integer)
1130 %status maybe
1131 %pragma variants c1 c2 cv c3 sm
1133 Returns the TARG agent's width.
1135 void caosVM::v_WDTH() {
1136 VM_VERIFY_SIZE(0)
1138 valid_agent(targ);
1139 result.setInt(targ->getWidth());
1143 PLNE (command) depth (integer)
1144 %status maybe
1146 Sets the plane (the z-order) of the TARG agent. Higher values are closer to the camera.
1148 void caosVM::c_PLNE() {
1149 VM_VERIFY_SIZE(1)
1150 VM_PARAM_INTEGER(depth)
1152 valid_agent(targ);
1153 targ->setZOrder(depth);
1157 TINT (command) red_tint (integer) green_tint (integer) blue_tint (integer) rotation (integer) swap (integer)
1158 %status maybe
1160 Sets the tinting of the TARG agent to the given red, blue, and green values.
1162 void caosVM::c_TINT() {
1163 VM_VERIFY_SIZE(5)
1164 VM_PARAM_INTEGER(swap)
1165 VM_PARAM_INTEGER(rotation)
1166 VM_PARAM_INTEGER(blue_tint)
1167 VM_PARAM_INTEGER(green_tint)
1168 VM_PARAM_INTEGER(red_tint)
1170 caos_assert(red_tint >= 0 && red_tint <= 256);
1171 caos_assert(green_tint >= 0 && green_tint <= 256);
1172 caos_assert(blue_tint >= 0 && blue_tint <= 256);
1173 caos_assert(swap >= 0 && swap <= 256);
1174 caos_assert(rotation >= 0 && rotation <= 256);
1176 SpritePart *p = getCurrentSpritePart();
1177 caos_assert(p);
1178 p->tint(red_tint, green_tint, blue_tint, rotation, swap);
1182 RNGE (command) distance (float)
1183 %status maybe
1185 Sets the TARG agent's range (i.e., the distance it can see and hear).
1187 void caosVM::c_RNGE() {
1188 VM_VERIFY_SIZE(1)
1189 VM_PARAM_FLOAT(distance)
1191 valid_agent(targ);
1192 targ->range = distance;
1196 RNGE (integer)
1197 %status maybe
1199 Returns the TARG agent's range.
1201 void caosVM::v_RNGE() {
1202 VM_VERIFY_SIZE(0)
1203 valid_agent(targ);
1204 result.setFloat(targ->range.getFloat());
1208 RNGE (variable)
1209 %status maybe
1210 %pragma variants c2
1211 %pragma implementation caosVM::v_RNGE_c2
1213 Returns the TARG agent's range.
1215 CAOS_LVALUE_TARG_SIMPLE(RNGE_c2, targ->range);
1218 TRAN (integer) x (integer) y (integer)
1219 %status maybe
1221 Tests if the pixel at (x,y) on the TARG agent is transparent.
1222 Returns 0 or 1.
1224 void caosVM::v_TRAN() {
1225 VM_VERIFY_SIZE(2)
1226 VM_PARAM_INTEGER(y)
1227 VM_PARAM_INTEGER(x)
1229 valid_agent(targ);
1230 CompoundPart *s = targ->part(0); assert(s);
1231 SpritePart *p = dynamic_cast<SpritePart *>(s);
1232 caos_assert(p);
1233 caos_assert(x >= 0 && x <= (int)p->getWidth());
1234 caos_assert(y >= 0 && y <= (int)p->getHeight());
1235 if (p->transparentAt(x, y))
1236 result.setInt(1);
1237 else
1238 result.setInt(0);
1242 TRAN (command) transparency (integer) part_no (integer)
1243 %status maybe
1245 Sets the TARG agent's behaviour with regard to transparency. If set to 1, invisible
1246 parts of the agent can't be clicked. If 0, anywhere on the agent (including transparent
1247 parts) can be clicked.
1249 void caosVM::c_TRAN() {
1250 VM_VERIFY_SIZE(2)
1251 VM_PARAM_INTEGER(part_no)
1252 VM_PARAM_INTEGER(transparency)
1254 valid_agent(targ);
1255 // TODO: handle -1?
1256 CompoundPart *s = targ->part(part_no);
1257 caos_assert(s);
1258 SpritePart *p = dynamic_cast<SpritePart *>(s);
1259 caos_assert(p);
1260 p->is_transparent = transparency;
1264 HGHT (integer)
1265 %status maybe
1266 %pragma variants c1 c2 cv c3 sm
1268 Returns the TARG agent's height.
1270 void caosVM::v_HGHT() {
1271 VM_VERIFY_SIZE(0)
1272 valid_agent(targ);
1274 result.setInt(targ->getHeight());
1278 HAND (string)
1279 %status maybe
1281 Returns the name of the Hand; default is 'hand'.
1283 void caosVM::v_HAND() {
1284 VM_VERIFY_SIZE(0)
1286 result.setString(world.hand()->name);
1290 HAND (command) name (string)
1291 %status maybe
1293 Sets the name of the Hand.
1295 void caosVM::c_HAND() {
1296 VM_VERIFY_SIZE(1)
1297 VM_PARAM_STRING(name)
1299 world.hand()->name = name;
1303 TICK (integer)
1304 %status maybe
1305 %pragma variants c2 cv c3 sm
1307 Return the agent timer tick rate of the TARG agent.
1309 void caosVM::v_TICK() {
1310 VM_VERIFY_SIZE(0)
1312 valid_agent(targ);
1313 result.setInt(targ->timerrate);
1317 PUPT (command) pose (integer) x (integer) y (integer)
1318 %status maybe
1320 Sets relative x/y coordinates for the location in the world where the TARG agent picks up
1321 objects. The pose is relative to the first image set in NEW: (not BASE).
1323 void caosVM::c_PUPT() {
1324 VM_VERIFY_SIZE(3)
1325 VM_PARAM_INTEGER(y)
1326 VM_PARAM_INTEGER(x)
1327 VM_PARAM_INTEGER(pose)
1329 valid_agent(targ);
1331 // this is basically a copy of PUHL, change that first
1332 if (pose == -1) {
1333 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1334 if (s) {
1335 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1336 targ->carry_points[i] = std::pair<int, int>(x, y);
1338 } else {
1339 // ..Assume a single pose for non-sprite parts.
1340 targ->carry_points[0] = std::pair<int, int>(x, y);
1342 } else {
1343 targ->carry_points[pose] = std::pair<int, int>(x, y);
1348 SETV PUPT (command) pose (integer) x (integer) y (integer)
1349 %status maybe
1350 %pragma variants c2
1352 void caosVM::c_SETV_PUPT() {
1353 c_PUPT();
1357 STPT (command)
1358 %status maybe
1360 Stop the script running in TARG, if any.
1362 void caosVM::c_STPT() {
1363 valid_agent(targ);
1364 targ->stopScript();
1368 DCOR (command) core_on (integer)
1369 %status done
1371 %pragma variants all
1373 Turns the display of the TARG agent's physical core on and off. Gives a general idea of
1374 its size and location (including invisible agents).
1376 void caosVM::c_DCOR() {
1377 VM_PARAM_INTEGER(core_on)
1379 valid_agent(targ);
1380 targ->displaycore = core_on;
1384 MIRA (integer)
1385 %status maybe
1387 Determines whether or not the TARG agent's current sprite is mirrored. Returns 0 or 1.
1389 void caosVM::v_MIRA() {
1390 valid_agent(targ);
1392 // TODO: correct?
1393 SpritePart *p = getCurrentSpritePart();
1394 caos_assert(p);
1396 result.setInt(p->draw_mirrored);
1400 MIRA (command) mirror_on (integer)
1401 %status maybe
1403 Turns mirroring of the TARG agent's current sprite on or off (0 or 1).
1405 void caosVM::c_MIRA() {
1406 VM_PARAM_INTEGER(mirror_on)
1408 valid_agent(targ);
1410 // TODO: what does 'current sprite' mean?
1411 // TODO: correct?
1412 SpritePart *p = getCurrentSpritePart();
1413 caos_assert(p);
1415 p->draw_mirrored = mirror_on;
1419 DISQ (float) other (agent)
1420 %status maybe
1422 Calculates the square of the distance between the centers of the TARG agent and the given
1423 agent.
1425 void caosVM::v_DISQ() {
1426 VM_PARAM_VALIDAGENT(other)
1428 valid_agent(targ);
1430 float x = (targ->x + (targ->getWidth() / 2.0f)) - (other->x + (other->getWidth() / 2.0f));
1431 float y = (targ->y + (targ->getHeight() / 2.0f)) - (other->y + (other->getHeight() / 2.0f));
1433 result.setFloat(x*x + y*y);
1437 ALPH (command) alpha_value (integer) enable (integer)
1438 %status maybe
1440 Sets the degree of alpha blending on the TARG agent, to a value from 0 (solid) to 256
1441 (invisible). The second parameter will turn alpha blending on and off.
1443 void caosVM::c_ALPH() {
1444 VM_PARAM_INTEGER(enable)
1445 VM_PARAM_INTEGER(alpha_value)
1447 if (alpha_value < 0) alpha_value = 0;
1448 else if (alpha_value > 255) alpha_value = 255;
1450 valid_agent(targ);
1452 CompoundAgent *c = dynamic_cast<CompoundAgent *>(targ.get());
1453 if (c && part == -1) {
1454 for (std::vector<CompoundPart *>::iterator i = c->parts.begin(); i != c->parts.end(); i++) {
1455 (*i)->has_alpha = enable;
1456 (*i)->alpha = alpha_value;
1458 } else {
1459 CompoundPart *p = targ->part(part);
1460 caos_assert(p);
1461 p->has_alpha = enable;
1462 p->alpha = alpha_value;
1467 HELD (agent)
1468 %status maybe
1470 Returns the agent currently held by the TARG agent, or a random one if there are more than one.
1472 void caosVM::v_HELD() {
1473 valid_agent(targ);
1475 // TODO: this whole thing perhaps belongs in a virtual function
1476 Vehicle *v = dynamic_cast<Vehicle *>(targ.get());
1477 if (v) {
1478 // TODO: it should be random .. ?
1479 if (v->passengers.size())
1480 result.setAgent(v->passengers[0]);
1481 else
1482 result.setAgent(0);
1483 } else {
1484 result.setAgent(targ->carrying);
1489 GALL (command) spritefile (string) first_image (integer)
1490 %status maybe
1492 Changes the sprite file and first image associated with the TARG agent or current PART.
1494 void caosVM::c_GALL() {
1495 VM_PARAM_INTEGER(first_image)
1496 VM_PARAM_STRING(spritefile)
1498 SpritePart *p = getCurrentSpritePart();
1499 caos_assert(p);
1500 p->changeSprite(spritefile, first_image);
1504 GALL (string)
1505 %status maybe
1507 Returns the name of the sprite file associated with the TARG agent or current PART, or a blank string if part# is invalid on a compound agent.
1509 void caosVM::v_GALL() {
1510 SpritePart *p = getCurrentSpritePart();
1511 if (p)
1512 result.setString(p->getSprite()->getName());
1513 else
1514 result.setString("");
1518 SEEE (integer) first (agent) second (agent)
1519 %status maybe
1521 Returns 1 if the first agent can see the other, or 0 otherwise.
1523 void caosVM::v_SEEE() {
1524 VM_PARAM_VALIDAGENT(second)
1525 VM_PARAM_VALIDAGENT(first)
1527 if (agentIsVisible(first.get(), second.get()))
1528 result.setInt(1);
1529 else
1530 result.setInt(0);
1534 TINT (integer) attribute (integer)
1535 %status stub
1537 Returns the tint value for TARG agent. Pass 1 for red, 2 for blue, 3 for green, 4 for rotation or 5 for swap.
1539 void caosVM::v_TINT() {
1540 VM_PARAM_INTEGER(attribute)
1542 valid_agent(targ);
1543 result.setInt(0); // TODO
1547 TINO (command) red (integer) green (integer) blue (integer) rotation (integer) swap (integer)
1548 %status stub
1550 Works like the TINT command, but only applies the tint to the current frame, and discards the rest.
1552 void caosVM::c_TINO() {
1553 VM_PARAM_INTEGER(swap)
1554 VM_PARAM_INTEGER(rotation)
1555 VM_PARAM_INTEGER(blue)
1556 VM_PARAM_INTEGER(green)
1557 VM_PARAM_INTEGER(red)
1559 // TODO
1563 DROP (command)
1564 %status stub
1565 %pragma variants c1 c2 cv c3 sm
1566 %cost c1,c2 0
1568 Causes the TARG agent to drop what it is carrying in a safe location.
1570 void caosVM::c_DROP() {
1571 valid_agent(targ);
1573 // TODO
1574 // TODO: only creatures in c1 (and c2?)
1577 AgentRef findNextAgent(AgentRef previous, unsigned char family, unsigned char genus, unsigned short species, bool forward) {
1578 if (world.agents.size() == 0) return AgentRef(); // shouldn't happen..
1580 AgentRef firstagent;
1581 bool foundagent = false;
1583 std::list<boost::shared_ptr<Agent> >::iterator i;
1584 if (forward)
1585 i = world.agents.begin();
1586 else {
1587 // TODO: i doubt this works
1588 i = world.agents.end();
1589 i--;
1592 // Loop through all the agents.
1593 while (true) {
1594 Agent *a = i->get();
1595 if (a && (a->family == family || family == 0))
1596 if (a->genus == genus || genus == 0)
1597 if (a->species == species || species == 0) {
1598 if (!firstagent) firstagent = a;
1599 if (foundagent) return AgentRef(a); // This is the agent we want!
1600 if (a == previous) foundagent = true;
1603 // Step through the list. Break if we need to.
1604 if (!forward && i == world.agents.begin()) break;
1605 if (forward) i++; else i--;
1606 if (forward && i == world.agents.end()) break;
1609 // Either we didn't find the previous agent, or we're at the end. Either way, return the first agent found.
1610 return firstagent;
1614 NCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1615 %status maybe
1617 void caosVM::v_NCLS() {
1618 VM_PARAM_INTEGER(species)
1619 VM_PARAM_INTEGER(genus)
1620 VM_PARAM_INTEGER(family)
1621 VM_PARAM_AGENT(previous)
1623 result.setAgent(findNextAgent(previous, family, genus, species, true));
1627 PCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1628 %status maybe
1630 void caosVM::v_PCLS() {
1631 VM_PARAM_INTEGER(species)
1632 VM_PARAM_INTEGER(genus)
1633 VM_PARAM_INTEGER(family)
1634 VM_PARAM_AGENT(previous)
1636 result.setAgent(findNextAgent(previous, family, genus, species, false));
1640 TCOR (integer) topy (float) bottomy (float) leftx (float) rightx (float)
1641 %status stub
1643 void caosVM::v_TCOR() {
1644 VM_PARAM_FLOAT(rightx)
1645 VM_PARAM_FLOAT(leftx)
1646 VM_PARAM_FLOAT(bottomy)
1647 VM_PARAM_FLOAT(topy)
1649 result.setInt(0); // TODO
1653 CORE (command) topy (float) bottomy (float) leftx (float) rightx (float)
1654 %status stub
1656 void caosVM::c_CORE() {
1657 VM_PARAM_FLOAT(rightx)
1658 VM_PARAM_FLOAT(leftx)
1659 VM_PARAM_FLOAT(bottomy)
1660 VM_PARAM_FLOAT(topy)
1662 // TODO
1666 TWIN (agent) source (agent) null_vars (integer)
1667 %status stub
1669 void caosVM::v_TWIN() {
1670 VM_PARAM_INTEGER(null_vars)
1671 VM_PARAM_VALIDAGENT(source)
1673 result.setAgent(0); // TODO
1677 ACTV (variable)
1678 %status maybe
1679 %pragma variants c1 c2
1681 CAOS_LVALUE_TARG_SIMPLE(ACTV, targ->actv);
1684 THRT (variable)
1685 %status maybe
1686 %pragma variants c2
1688 CAOS_LVALUE_TARG_SIMPLE(THRT, targ->thrt);
1691 SIZE (variable)
1692 %status stub
1693 %pragma variants c2
1695 // TODO: stub because this likely == perm
1696 CAOS_LVALUE_TARG_SIMPLE(SIZE, targ->size);
1699 GRAV (variable)
1700 %status stub
1701 %pragma variants c2
1703 // TODO: stub because this likely == falling
1704 CAOS_LVALUE_TARG_SIMPLE(GRAV, targ->grav);
1707 SETV CLS2 (command) family (integer) genus (integer) species (integer)
1708 %status maybe
1709 %pragma variants c2
1711 Creatures 2 command to set the family, genus and species of an agent.
1713 void caosVM::c_SETV_CLS2() {
1714 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
1715 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
1716 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
1718 valid_agent(targ);
1720 targ->setClassifier(family, genus, species);
1724 SLIM (command)
1725 %status stub
1726 %pragma variants c1 c2
1727 %cost c1,c2 0
1729 void caosVM::c_SLIM() {
1730 // TODO: probably shouldn't do anything, but make sure :)
1734 BHVR (command) click (integer) touch (integer)
1735 %status stub
1736 %pragma variants c1 c2
1737 %pragma implementation caosVM::c_BHVR_c2
1738 %cost c1,c2 0
1740 void caosVM::c_BHVR_c2() {
1741 VM_PARAM_INTEGER(touch)
1742 VM_PARAM_INTEGER(click)
1744 valid_agent(targ);
1746 // see Agent::handleClick for details of what these values mean
1747 switch (click) {
1748 // clicks have no effect
1749 case 0: targ->clac[0] = -1; targ->clac[1] = -1; targ->clac[2] = -1; break;
1750 // monostable
1751 case 1: targ->clac[0] = 0; targ->clac[1] = -1; targ->clac[2] = -1; break;
1752 // retriggerable monostable
1753 case 2: targ->clac[0] = 0; targ->clac[1] = 0; targ->clac[2] = -1; break;
1754 // toggle
1755 case 3: targ->clac[0] = 0; targ->clac[1] = 2; targ->clac[2] = -1; break;
1756 // cycle
1757 case 4: targ->clac[0] = 0; targ->clac[1] = 1; targ->clac[2] = 2; break;
1758 default:
1759 // C2, at least, seems to produce random garbage (going off the end of a
1760 // lookup table?) in this situation .. let's not
1761 throw creaturesException(boost::str(boost::format("silly BHVR click value: %d") % click));
1764 // TODO
1768 SETV CLAS (command) identifier (integer)
1769 %status maybe
1770 %pragma variants c1
1772 Set family, genus and species of the target agent. Creatures 1 era command.
1774 void caosVM::c_SETV_CLAS() {
1775 VM_PARAM_INTEGER(identifier)
1777 valid_agent(targ);
1779 targ->setClassifier(
1780 (identifier >> 24) & 0xff,
1781 (identifier >> 16) & 0xff,
1782 (identifier >> 8) & 0xff
1787 LIML (integer)
1788 %status maybe
1789 %pragma variants c1 c2
1791 void caosVM::v_LIML() {
1792 // TODO: is this remotely sane? if so, unstub.
1793 valid_agent(targ);
1795 if (targ->invehicle) {
1796 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1797 result.setInt((int)v->x + v->cabinleft);
1798 } else {
1799 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1801 if (r) result.setInt(r->x_left);
1802 else result.setInt(0);
1807 LIMT (integer)
1808 %status maybe
1809 %pragma variants c1 c2
1811 void caosVM::v_LIMT() {
1812 // TODO: is this remotely sane? if so, unstub.
1813 valid_agent(targ);
1815 if (targ->invehicle) {
1816 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1817 result.setInt((int)v->y + v->cabintop);
1818 } else {
1819 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1821 if (r) result.setInt(r->y_left_ceiling);
1822 else result.setInt(0);
1827 LIMR (integer)
1828 %status maybe
1829 %pragma variants c1 c2
1831 void caosVM::v_LIMR() {
1832 // TODO: is this remotely sane? if so, unstub.
1833 valid_agent(targ);
1835 if (targ->invehicle) {
1836 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1837 result.setInt((int)v->x + v->cabinright);
1838 } else {
1839 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1841 if (r) result.setInt(r->x_right);
1842 else result.setInt(8352); // TODO
1847 LIMB (integer)
1848 %status maybe
1849 %pragma variants c1 c2
1850 %pragma implementation caosVM::v_LIMB_c1
1852 void caosVM::v_LIMB_c1() {
1853 // TODO: is this remotely sane? if so, unstub.
1854 valid_agent(targ);
1856 if (targ->invehicle) {
1857 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1858 result.setInt((int)v->y + v->cabinbottom);
1859 } else {
1860 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1862 if (r) result.setInt(r->y_left_floor);
1863 else result.setInt(1200); // TODO
1868 OBJP (variable)
1869 %status maybe
1870 %pragma variants c1 c2
1872 // TODO: c1 scripts seem to depend on this being from OWNR, but is that always the case?
1873 CAOS_LVALUE_WITH_SIMPLE(OBJP, owner, owner->objp);
1876 XIST (integer) agent (agent)
1877 %status maybe
1878 %pragma variants c2
1880 Undocumented C2 command; returns 1 if specified agent exists, or 0 otherwise (ie, if it is null).
1882 void caosVM::v_XIST() {
1883 VM_PARAM_AGENT(agent)
1885 if (agent.get())
1886 result.setInt(1);
1887 else
1888 result.setInt(0);
1892 SCLE (command) pose (integer) scaleby (integer)
1893 %status stub
1895 void caosVM::c_SCLE() {
1896 VM_PARAM_INTEGER(scaleby)
1897 VM_PARAM_INTEGER(pose)
1899 // TODO
1903 IMGE (command) filename (string)
1904 %status stub
1906 void caosVM::c_IMGE() {
1907 VM_PARAM_STRING(filename)
1909 // TODO
1913 TNTW (command) index (integer)
1914 %status stub
1916 void caosVM::c_TNTW() {
1917 VM_PARAM_INTEGER(index)
1919 // TODO
1923 PRNT (command) pose (integer)
1924 %status stub
1926 void caosVM::c_PRNT() {
1927 VM_PARAM_INTEGER(pose)
1929 // TODO
1933 TCAR (agent)
1934 %status stub
1935 %pragma variants c2
1937 void caosVM::v_TCAR() {
1938 valid_agent(targ);
1940 result.setAgent(0);
1944 EDIT (command)
1945 %status stub
1946 %pragma variants c1 c2
1948 Attach the target agent to the mouse cursor for positioning purposes.
1949 Presently just causes the hand to pick it up.
1951 void caosVM::c_EDIT() {
1952 valid_agent(targ);
1954 world.hand()->addCarried(targ);
1958 FRZN (variable)
1959 %status stub
1960 %pragma variants c2
1962 void caosVM::v_FRZN() {
1963 valid_agent(targ);
1964 caosVar r = targ->frozen ? 1 : 0;
1965 valueStack.push_back(r);
1967 void caosVM::s_FRZN() {
1968 VM_PARAM_VALUE(newvalue)
1969 caos_assert(newvalue.hasInt());
1971 valid_agent(targ);
1972 targ->frozen = newvalue.getInt();
1975 #include "bmpImage.h"
1978 BLCK (command) width (integer) height (integer)
1979 %status maybe
1980 %pragma variants sm
1982 void caosVM::c_BLCK() {
1983 VM_PARAM_INTEGER(height)
1984 VM_PARAM_INTEGER(width)
1986 SpritePart *p = getCurrentSpritePart();
1987 caos_assert(p);
1988 shared_ptr<creaturesImage> i = p->getSprite();
1989 bmpImage *img = dynamic_cast<bmpImage *>(i.get());
1990 caos_assert(img);
1992 img->setBlockSize(width, height);
1995 /* vim: set noet: */