add a hack to deal with ACTV on compound agents in c1/c2
[openc2e.git] / caosVM_agent.cpp
blob4e6ae817b2df76f63cbfb983a81de1674a5b4a97
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, textx, texty, background_colour, chalk_colour, alias_colour);
317 a->finishInit();
318 setTarg(a);
322 NEW: CBUB (command) sprite_file (bareword) image_count (integer) first_image (integer) stringid (integer)
323 %status maybe
324 %pragma variants c2
326 void caosVM::c_NEW_CBUB() {
327 VM_PARAM_INTEGER(stringid)
328 VM_PARAM_INTEGER(first_image)
329 VM_PARAM_INTEGER(image_count)
330 VM_PARAM_STRING(sprite_file)
332 throw creaturesException("compound bubble objects are not supported yet"); // TODO
336 TARG (agent)
337 %status maybe
338 %pragma variants c1 c2 cv c3 sm
340 Returns TARG, the currently-targeted agent.
342 void caosVM::v_TARG() {
343 VM_VERIFY_SIZE(0)
344 result.setAgent(targ);
348 OWNR (agent)
349 %status maybe
350 %pragma variants c1 c2 cv c3 sm
351 %cost c1,c2 0
353 Returns OWNR, the agent that is running the script.
355 void caosVM::v_OWNR() {
356 VM_VERIFY_SIZE(0)
357 result.setAgent(owner);
361 NULL (agent)
362 %status maybe
364 Returns a null (zero) agent.
366 void caosVM::v_NULL() {
367 static const AgentRef nullref;
368 VM_VERIFY_SIZE(0)
369 result.setAgent(nullref);
373 POSE (command) pose (integer)
374 %status maybe
375 %pragma variants c1 c2 cv c3 sm
376 %cost c1,c2 1
378 Sets the displayed sprite of TARG to the frame in the sprite file with the given integer.
380 void caosVM::c_POSE() {
381 VM_VERIFY_SIZE(1)
382 VM_PARAM_INTEGER(pose)
384 AnimatablePart *p = getCurrentAnimatablePart();
385 caos_assert(p);
387 SpritePart *s = dynamic_cast<SpritePart *>(p);
388 if (s)
389 caos_assert(s->getFirstImg() + s->getBase() + pose < s->getSprite()->numframes());
391 p->setPose(pose);
395 ATTR (command) attr (integer)
396 %status maybe
398 Sets attributes of the TARG agent.
400 void caosVM::c_ATTR() {
401 VM_VERIFY_SIZE(1)
402 VM_PARAM_INTEGER(attr)
403 valid_agent(targ);
405 bool oldfloat = targ->floatable();
406 targ->setAttributes(attr);
408 // TODO: this is an icky hack to enable floating, we should write correct floating
409 // behaviour so we don't need to maintain floating lists like this :/
410 if (oldfloat != targ->floatable()) {
411 if (targ->floatable())
412 targ->floatSetup();
413 else
414 targ->floatRelease();
419 ATTR (variable)
420 %status maybe
421 %pragma variants c1 c2 cv c3 sm
423 Attributes of the TARG agent.
425 CAOS_LVALUE_TARG_SIMPLE(ATTR, targ->attr);
428 TICK (command) tickrate (integer)
429 %status maybe
430 %pragma variants c1 c2 cv c3 sm
431 %cost c1,c2 0
433 Initiates the agent timer-- the Timer script will then be run once every tickrate ticks.
434 Setting tickrate to zero will stop the timer.
436 void caosVM::c_TICK() {
437 VM_VERIFY_SIZE(1)
438 VM_PARAM_INTEGER(tickrate)
439 valid_agent(targ);
440 targ->setTimerRate(tickrate);
444 BHVR (command) bhvr (integer)
445 %status maybe
447 Sets the behaviour of the TARG agent.
449 void caosVM::c_BHVR() {
450 VM_VERIFY_SIZE(1)
451 VM_PARAM_INTEGER(bhvr)
453 valid_agent(targ);
455 // reset bhvr
456 targ->cr_can_push = targ->cr_can_pull = targ->cr_can_stop =
457 targ->cr_can_hit = targ->cr_can_eat = targ->cr_can_pickup = false;
459 if (bhvr & 0x1) // creature can push
460 targ->cr_can_push = true;
461 if (bhvr & 0x2) // creature can pull
462 targ->cr_can_pull = true;
463 if (bhvr & 0x4) // creature can stop
464 targ->cr_can_stop = true;
465 if (bhvr & 0x8) // creature can hit
466 targ->cr_can_hit = true;
467 if (bhvr & 0x10) // creature can eat
468 targ->cr_can_eat = true;
469 if (bhvr & 0x20) // creature can pick up
470 targ->cr_can_pickup = true;
474 TARG (command) agent (agent)
475 %status maybe
476 %pragma variants c1 c2 cv c3 sm
477 %cost c1,c2 0
479 Sets TARG (the target agent) to the given agent.
481 void caosVM::c_TARG() {
482 VM_VERIFY_SIZE(1)
483 VM_PARAM_AGENT(a)
484 setTarg(a);
488 FROM (agent)
489 %status maybe
490 %pragma variants c1 c2 cv sm
492 Returns the agent that sent the message being processed, or NULL if no agent was involved.
494 void caosVM::v_FROM() {
495 result.setAgent(from.getAgent());
499 FROM (variable)
500 %status maybe
501 %pragma variants c3
502 %pragma implementation caosVM::v_FROM_ds
504 Returns the agent that sent the message being processed, or NULL if no agent was involved.
506 // Returns a variable because DS is insane and uses this for network events too (and so, of course, scripts abuse it).
507 CAOS_LVALUE_SIMPLE(FROM_ds, from);
510 POSE (integer)
511 %status maybe
512 %pragma variants c1 c2 cv c3 sm
514 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.
516 void caosVM::v_POSE() {
517 VM_VERIFY_SIZE(0)
519 valid_agent(targ);
521 SpritePart *p = getCurrentSpritePart();
522 if (p)
523 result.setInt(p->getPose());
524 else
525 result.setInt(-1);
529 KILL (command) agent (agent)
530 %status maybe
531 %pragma variants c1 c2 cv c3 sm
532 %cost c1,c2 1
534 Destroys the agent in question. However, you cannot destroy PNTR.
535 Remember, use DEAD first for Creatures!
537 void caosVM::c_KILL() {
538 VM_VERIFY_SIZE(1)
539 VM_PARAM_VALIDAGENT(a)
541 // note that kill is a virtual function which doesn't work on PNTR
542 a->kill();
546 ANIM (command) poselist (bytestring)
547 %status maybe
549 Sets the animation string for TARG, in the format '1 2 3 4'.
550 If it ends with '255', loops back to beginning; if it ends with '255 X', loops back to frame X.
552 <i>todo: compound agent stuff</i>
554 void caosVM::c_ANIM() {
555 VM_VERIFY_SIZE(1)
556 VM_PARAM_BYTESTR(bs)
558 valid_agent(targ);
560 AnimatablePart *p = getCurrentAnimatablePart();
561 caos_assert(p);
562 p->animation = bs;
564 if (!bs.empty()) p->setFrameNo(0); // TODO: correct?
568 ANIM (command) animstring (string)
569 %status maybe
570 %pragma variants c1 c2
571 %pragma implementation caosVM::c_ANIM_c2
572 %cost c1,c2 1
574 Sets the animation string for TARG, in the format '1234'.
575 If it ends with 'R', loops back to the beginning.
577 void caosVM::c_ANIM_c2() {
578 VM_PARAM_STRING(animstring)
580 valid_agent(targ);
582 // TODO: support creatures (using AnimatablePart, see c2e ANIM) for this (with format like "001002003R")
583 if (dynamic_cast<SkeletalCreature *>(targ.get())) return;
585 SpritePart *p = getCurrentSpritePart();
586 caos_assert(p);
588 p->animation.clear();
590 for (unsigned int i = 0; i < animstring.size(); i++) {
591 if (animstring[i] == 'R') {
592 p->animation.push_back(255);
593 } else if (animstring[i] >= 48 && animstring[i] <= 57) {
594 p->animation.push_back(animstring[i] - 48);
595 } else if (animstring[i] >= 97 && animstring[i] <= 122) {
596 // TODO: c1 grendel eggs have 'a' at the end of their animation strings, this is an untested attempt to handle that
597 p->animation.push_back(animstring[i] - 97);
598 } else {
599 p->animation.clear();
600 throw creaturesException(std::string("old-style animation string contained '") + animstring[i] + "', which we didn't understand");
604 if (!animstring.empty()) p->setFrameNo(0); // TODO: correct?
608 ANMS (command) poselist (string)
609 %status maybe
611 Exactly like ANIM, only using a string and not a bytestring for poselist source.
613 void caosVM::c_ANMS() {
614 VM_PARAM_STRING(poselist)
616 // TODO: technically, we should parse this properly, also do error checking
617 bytestring_t animation;
619 std::string t;
620 for (unsigned int i = 0; i < poselist.size(); i++) {
621 if (poselist[i] == ' ')
622 if (!t.empty()) {
623 int n = atoi(t.c_str());
624 caos_assert(n >= 0 && n < 256);
625 animation.push_back(n);
627 else
628 t = t + poselist[i];
631 AnimatablePart *p = getCurrentAnimatablePart();
632 caos_assert(p);
633 p->animation = animation;
635 if (!animation.empty()) p->setFrameNo(0); // TODO: correct?
639 ABBA (integer)
640 %status maybe
642 Returns the first_image (ie, absolute base) value for the current agent/part, or -1 if part# doesn't exist on a compound agent.
644 void caosVM::v_ABBA() {
645 VM_VERIFY_SIZE(0)
647 SpritePart *p = getCurrentSpritePart();
648 if (p)
649 result.setInt(p->getFirstImg());
650 else
651 result.setInt(-1);
655 BASE (command) index (integer)
656 %status maybe
657 %pragma variants c1 c2 cv c3 sm
658 %cost c1,c2 0
660 Sets the frame in the TARG agent's spritefile that will be used as its base image.
661 This is relative to the first image set with one of the NEW: commands.
663 void caosVM::c_BASE() {
664 VM_VERIFY_SIZE(1)
665 VM_PARAM_INTEGER(index)
667 valid_agent(targ);
669 SpritePart *p = getCurrentSpritePart();
670 caos_assert(p);
671 // Note that we don't check validity here because a lot of code changes BASE and then only afterwards POSE/ANIM.
672 p->setBase(index);
676 BASE (integer)
677 %status maybe
679 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.
681 void caosVM::v_BASE() {
682 VM_VERIFY_SIZE(0)
684 SpritePart *p = getCurrentSpritePart();
685 if (p)
686 result.setInt(p->getBase());
687 else
688 result.setInt(-1);
692 BHVR (integer)
693 %status maybe
695 Returns the behaviour of the TARG agent.
697 void caosVM::v_BHVR() {
698 VM_VERIFY_SIZE(0)
700 valid_agent(targ);
702 unsigned char bvr = 0;
704 if (targ->cr_can_push) bvr += 0x1;
705 if (targ->cr_can_pull) bvr += 0x2;
706 if (targ->cr_can_stop) bvr += 0x4;
707 if (targ->cr_can_hit) bvr += 0x8;
708 if (targ->cr_can_eat) bvr += 0x10;
709 if (targ->cr_can_pickup) bvr += 0x20;
711 result.setInt(bvr);
715 CARR (agent)
716 %status maybe
718 Returns the agent that is carrying the TARG agent. If TARG is not being carried, returns
719 NULL.
721 void caosVM::v_CARR() {
722 VM_VERIFY_SIZE(0)
723 valid_agent(targ);
725 // TODO: muh, should totally be virtual
726 if (targ->invehicle)
727 result.setAgent(targ->invehicle);
728 else
729 result.setAgent(targ->carriedby);
733 CARR (agent)
734 %status maybe
735 %pragma variants c1 c2
736 %pragma implementation caosVM::v_CARR_c1
738 Returns the agent that is carrying the OWNR agent. If OWNR is not being carried, returns
739 NULL.
741 void caosVM::v_CARR_c1() {
742 VM_VERIFY_SIZE(0)
743 valid_agent(owner);
745 result.setAgent(owner->carriedby);
749 FMLY (integer)
750 %status maybe
751 %pragma variants c1 c2 cv c3 sm
753 Returns the family of the TARG agent.
755 void caosVM::v_FMLY() {
756 VM_VERIFY_SIZE(0)
757 valid_agent(targ);
758 result.setInt(targ->family);
762 GNUS (integer)
763 %status maybe
764 %pragma variants c1 c2 cv c3 sm
766 Returns the genus of the TARG agent.
768 void caosVM::v_GNUS() {
769 VM_VERIFY_SIZE(0)
770 valid_agent(targ);
771 result.setInt(targ->genus);
775 SPCS (integer)
776 %status maybe
777 %pragma variants c1 c2 cv c3 sm
779 Returns the species of the TARG agent.
781 void caosVM::v_SPCS() {
782 VM_VERIFY_SIZE(0)
783 valid_agent(targ);
784 result.setInt(targ->species);
788 PLNE (integer)
789 %status maybe
791 Returns the plane (z-order) of the TARG agent.
793 void caosVM::v_PLNE() {
794 VM_VERIFY_SIZE(0)
795 valid_agent(targ);
796 result.setInt(targ->getZOrder());
800 PNTR (agent)
801 %status maybe
802 %pragma variants c1 c2 cv c3 sm
804 Returns the pointer agent (the Hand).
806 void caosVM::v_PNTR() {
807 VM_VERIFY_SIZE(0)
808 result.setAgent(world.hand());
811 #include "Engine.h" // for engine.version check, sigh
812 unsigned int calculateScriptId(unsigned int message_id) {
813 // aka, why oh why is this needed? Silly CL.
815 switch (message_id) {
816 case 2: /* deactivate */
817 return 0;
818 case 8: /* hilarious special case to fix c2 airlock */
819 if (engine.version < 3)
820 return 7;
821 else
822 return 8;
823 case 0: /* activate 1 */
824 case 1: /* activate 2 */
825 return message_id + 1;
828 return message_id;
832 MESG WRIT (command) agent (agent) message_id (integer)
833 %status maybe
834 %pragma variants c1 c2 cv c3 sm
835 %cost c1,c2 0
837 Sends a message of type message_id to the given agent. FROM will be set to OWNR unless
838 there is no agent involved in sending the message.
840 void caosVM::c_MESG_WRIT() {
841 VM_VERIFY_SIZE(2)
842 VM_PARAM_INTEGER(message_id)
843 VM_PARAM_VALIDAGENT(agent);
845 agent->queueScript(calculateScriptId(message_id), owner.get());
849 MESG WRT+ (command) agent (agent) message_id (integer) param_1 (anything) param_2 (anything) delay (integer)
850 %status maybe
851 %pragma variants c2 cv c3 sm
853 Sends a message of type message_id to the given agent, much like MESG WRIT, but with the
854 addition of parameters. The message will be sent after waiting the number of ticks set
855 in delay (except doesn't, right now. Delay must be set to zero for now.)
857 void caosVM::c_MESG_WRT() {
858 VM_VERIFY_SIZE(5)
859 VM_PARAM_INTEGER(delay)
860 VM_PARAM_VALUE(param_2)
861 VM_PARAM_VALUE(param_1)
862 VM_PARAM_INTEGER(message_id)
863 VM_PARAM_VALIDAGENT(agent)
865 // I'm not sure how to handle the 'delay'; is it a background delay, or do we actually block for delay ticks?
866 // TODO: fuzzie can't work out how on earth delays work in c2e, someone fixit
868 agent->queueScript(calculateScriptId(message_id), owner.get(), param_1, param_2);
872 TOTL (integer) family (integer) genus (integer) species (integer)
873 %status maybe
874 %pragma variants c1 c2 cv c3 sm
876 Returns the total number of in-game agents matching the given family/genus/species.
878 void caosVM::v_TOTL() {
879 VM_VERIFY_SIZE(3)
880 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
881 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
882 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
884 unsigned int x = 0;
885 for (std::list<boost::shared_ptr<Agent> >::iterator i = world.agents.begin(); i != world.agents.end(); i++) {
886 if (!*i) continue;
887 if ((*i)->family == family || family == 0)
888 if ((*i)->genus == genus || genus == 0)
889 if ((*i)->species == species || species == 0)
890 x++;
892 result.setInt(x);
896 SHOW (command) visibility (integer)
897 %status maybe
899 Sets visibility of the TARG agent to cameras. 0 = invisible, 1 = visible.
901 void caosVM::c_SHOW() {
902 VM_VERIFY_SIZE(1)
903 VM_PARAM_INTEGER(visibility)
904 caos_assert((visibility == 0) || (visibility == 1));
905 valid_agent(targ);
906 targ->visible = visibility;
910 SHOW (integer)
911 %status maybe
913 void caosVM::v_SHOW() {
914 valid_agent(targ);
915 result.setInt(targ->visible ? 1 : 0);
919 POSX (float)
920 %status maybe
921 %pragma variants c2 cv c3 sm
923 Returns the X position of the TARG agent in the world.
925 void caosVM::v_POSX() {
926 VM_VERIFY_SIZE(0)
927 valid_agent(targ);
928 result.setFloat(targ->x + (targ->getWidth() / 2.0f));
932 POSY (float)
933 %status maybe
934 %pragma variants c2 cv c3 sm
936 Returns the Y position of the TARG agent in the world.
938 void caosVM::v_POSY() {
939 VM_VERIFY_SIZE(0)
940 valid_agent(targ);
941 result.setFloat(targ->y + (targ->getHeight() / 2.0f));
945 FRAT (command) framerate (integer)
946 %status maybe
948 Sets the delay between frame changes of the TARG agent or current PART.
949 Must be from 1 to 255, 1 being the normal rate, 2 being half as quickly, and so on.
951 void caosVM::c_FRAT() {
952 VM_VERIFY_SIZE(1)
953 VM_PARAM_INTEGER(framerate)
955 caos_assert(framerate >= 1 && framerate <= 255);
956 valid_agent(targ);
958 SpritePart *p = getCurrentSpritePart();
959 caos_assert(p);
960 p->setFramerate(framerate);
961 p->framedelay = 0;
964 class blockUntilOver : public blockCond {
965 protected:
966 AgentRef targ;
967 int part;
968 public:
969 blockUntilOver(Agent *t, int p) : targ(t), part(p) {}
970 virtual bool operator()() {
971 bool blocking;
972 int fno, animsize;
974 if (!targ) return false;
976 CompoundPart *s = targ->part(part);
977 caos_assert(s);
978 AnimatablePart *p = dynamic_cast<AnimatablePart *>(s);
979 caos_assert(p);
981 fno = p->getFrameNo();
982 animsize = p->animation.size();
984 if (fno + 1 == animsize) blocking = false;
985 else if (animsize == 0) blocking = false;
986 else blocking = true;
987 return blocking;
993 OVER (command)
994 %status maybe
995 %pragma variants c1 c2 cv c3 sm
997 Waits (blocks the TARG agent) until the animation of the TARG agent or PART is over.
999 void caosVM::c_OVER() {
1000 valid_agent(targ);
1002 // TODO: The Burrows uses OVER in install script, so fuzzie's making this optional for now, but is this right?
1003 if (owner)
1004 startBlocking(new blockUntilOver(targ, part));
1008 PUHL (command) pose (integer) x (integer) y (integer)
1009 %status maybe
1011 Sets relative x/y coordinates for TARG's pickup point.
1012 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1014 void caosVM::c_PUHL() {
1015 VM_VERIFY_SIZE(3)
1016 VM_PARAM_INTEGER(y)
1017 VM_PARAM_INTEGER(x)
1018 VM_PARAM_INTEGER(pose)
1020 valid_agent(targ);
1022 if (pose == -1) {
1023 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1024 if (s) {
1025 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1026 targ->carried_points[i] = std::pair<int, int>(x, y);
1028 } else {
1029 // ..Assume a single pose for non-sprite parts.
1030 targ->carried_points[0] = std::pair<int, int>(x, y);
1032 } else {
1033 targ->carried_points[pose] = std::pair<int, int>(x, y);
1038 SETV PUHL (command) pose (integer) x (integer) y (integer)
1039 %status maybe
1040 %pragma variants c2
1042 Sets relative x/y coordinates for TARG's pickup point.
1043 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1045 void caosVM::c_SETV_PUHL() {
1046 c_PUHL();
1050 PUHL (integer) pose (integer) x_or_y (integer)
1051 %status maybe
1053 Returns the coordinate for TARG's pickup point. x_or_y should be 1 for x, or 2 for y.
1055 void caosVM::v_PUHL() {
1056 VM_PARAM_INTEGER(x_or_y)
1057 VM_PARAM_INTEGER(pose)
1059 valid_agent(targ);
1061 // TODO: this creates the variable if it doesn't exist yet, correct behaviour?
1062 if (x_or_y == 1) {
1063 result.setInt(targ->carried_points[pose].first);
1064 } else {
1065 caos_assert(x_or_y == 2);
1066 result.setInt(targ->carried_points[pose].second);
1071 POSL (float)
1072 %status maybe
1073 %pragma variants c1 c2 cv c3 sm
1075 Returns the position of the left side of TARG's bounding box.
1077 void caosVM::v_POSL() {
1078 VM_VERIFY_SIZE(0)
1080 valid_agent(targ);
1081 result.setFloat(targ->x);
1085 POST (float)
1086 %status maybe
1087 %pragma variants c1 c2 cv c3 sm
1089 Returns the position of the top side of TARG's bounding box.
1091 void caosVM::v_POST() {
1092 VM_VERIFY_SIZE(0)
1094 valid_agent(targ);
1095 result.setFloat(targ->y);
1099 POSR (float)
1100 %status maybe
1101 %pragma variants c1 c2 cv c3 sm
1103 Returns the position of the right side of TARG's bounding box.
1105 void caosVM::v_POSR() {
1106 VM_VERIFY_SIZE(0)
1108 valid_agent(targ);
1109 result.setFloat(targ->x + targ->getWidth());
1113 POSB (float)
1114 %status maybe
1115 %pragma variants c1 c2 cv c3 sm
1117 Returns the position of the bottom side of TARG's bounding box.
1119 void caosVM::v_POSB() {
1120 VM_VERIFY_SIZE(0)
1122 valid_agent(targ);
1123 result.setFloat(targ->y + targ->getHeight());
1127 WDTH (integer)
1128 %status maybe
1129 %pragma variants c1 c2 cv c3 sm
1131 Returns the TARG agent's width.
1133 void caosVM::v_WDTH() {
1134 VM_VERIFY_SIZE(0)
1136 valid_agent(targ);
1137 result.setInt(targ->getWidth());
1141 PLNE (command) depth (integer)
1142 %status maybe
1144 Sets the plane (the z-order) of the TARG agent. Higher values are closer to the camera.
1146 void caosVM::c_PLNE() {
1147 VM_VERIFY_SIZE(1)
1148 VM_PARAM_INTEGER(depth)
1150 valid_agent(targ);
1151 targ->setZOrder(depth);
1155 TINT (command) red_tint (integer) green_tint (integer) blue_tint (integer) rotation (integer) swap (integer)
1156 %status maybe
1158 Sets the tinting of the TARG agent to the given red, blue, and green values.
1160 void caosVM::c_TINT() {
1161 VM_VERIFY_SIZE(5)
1162 VM_PARAM_INTEGER(swap)
1163 VM_PARAM_INTEGER(rotation)
1164 VM_PARAM_INTEGER(blue_tint)
1165 VM_PARAM_INTEGER(green_tint)
1166 VM_PARAM_INTEGER(red_tint)
1168 caos_assert(red_tint >= 0 && red_tint <= 256);
1169 caos_assert(green_tint >= 0 && green_tint <= 256);
1170 caos_assert(blue_tint >= 0 && blue_tint <= 256);
1171 caos_assert(swap >= 0 && swap <= 256);
1172 caos_assert(rotation >= 0 && rotation <= 256);
1174 SpritePart *p = getCurrentSpritePart();
1175 caos_assert(p);
1176 p->tint(red_tint, green_tint, blue_tint, rotation, swap);
1180 RNGE (command) distance (float)
1181 %status maybe
1183 Sets the TARG agent's range (i.e., the distance it can see and hear).
1185 void caosVM::c_RNGE() {
1186 VM_VERIFY_SIZE(1)
1187 VM_PARAM_FLOAT(distance)
1189 valid_agent(targ);
1190 targ->range = distance;
1194 RNGE (integer)
1195 %status maybe
1197 Returns the TARG agent's range.
1199 void caosVM::v_RNGE() {
1200 VM_VERIFY_SIZE(0)
1201 valid_agent(targ);
1202 result.setFloat(targ->range.getFloat());
1206 RNGE (variable)
1207 %status maybe
1208 %pragma variants c2
1209 %pragma implementation caosVM::v_RNGE_c2
1211 Returns the TARG agent's range.
1213 CAOS_LVALUE_TARG_SIMPLE(RNGE_c2, targ->range);
1216 TRAN (integer) x (integer) y (integer)
1217 %status maybe
1219 Tests if the pixel at (x,y) on the TARG agent is transparent.
1220 Returns 0 or 1.
1222 void caosVM::v_TRAN() {
1223 VM_VERIFY_SIZE(2)
1224 VM_PARAM_INTEGER(y)
1225 VM_PARAM_INTEGER(x)
1227 valid_agent(targ);
1228 CompoundPart *s = targ->part(0); assert(s);
1229 SpritePart *p = dynamic_cast<SpritePart *>(s);
1230 caos_assert(p);
1231 caos_assert(x >= 0 && x <= (int)p->getWidth());
1232 caos_assert(y >= 0 && y <= (int)p->getHeight());
1233 if (p->transparentAt(x, y))
1234 result.setInt(1);
1235 else
1236 result.setInt(0);
1240 TRAN (command) transparency (integer) part_no (integer)
1241 %status maybe
1243 Sets the TARG agent's behaviour with regard to transparency. If set to 1, invisible
1244 parts of the agent can't be clicked. If 0, anywhere on the agent (including transparent
1245 parts) can be clicked.
1247 void caosVM::c_TRAN() {
1248 VM_VERIFY_SIZE(2)
1249 VM_PARAM_INTEGER(part_no)
1250 VM_PARAM_INTEGER(transparency)
1252 valid_agent(targ);
1253 // TODO: handle -1?
1254 CompoundPart *s = targ->part(part_no);
1255 caos_assert(s);
1256 SpritePart *p = dynamic_cast<SpritePart *>(s);
1257 caos_assert(p);
1258 p->is_transparent = transparency;
1262 HGHT (integer)
1263 %status maybe
1264 %pragma variants c1 c2 cv c3 sm
1266 Returns the TARG agent's height.
1268 void caosVM::v_HGHT() {
1269 VM_VERIFY_SIZE(0)
1270 valid_agent(targ);
1272 result.setInt(targ->getHeight());
1276 HAND (string)
1277 %status maybe
1279 Returns the name of the Hand; default is 'hand'.
1281 void caosVM::v_HAND() {
1282 VM_VERIFY_SIZE(0)
1284 result.setString(world.hand()->name);
1288 HAND (command) name (string)
1289 %status maybe
1291 Sets the name of the Hand.
1293 void caosVM::c_HAND() {
1294 VM_VERIFY_SIZE(1)
1295 VM_PARAM_STRING(name)
1297 world.hand()->name = name;
1301 TICK (integer)
1302 %status maybe
1303 %pragma variants c2 cv c3 sm
1305 Return the agent timer tick rate of the TARG agent.
1307 void caosVM::v_TICK() {
1308 VM_VERIFY_SIZE(0)
1310 valid_agent(targ);
1311 result.setInt(targ->timerrate);
1315 PUPT (command) pose (integer) x (integer) y (integer)
1316 %status maybe
1318 Sets relative x/y coordinates for the location in the world where the TARG agent picks up
1319 objects. The pose is relative to the first image set in NEW: (not BASE).
1321 void caosVM::c_PUPT() {
1322 VM_VERIFY_SIZE(3)
1323 VM_PARAM_INTEGER(y)
1324 VM_PARAM_INTEGER(x)
1325 VM_PARAM_INTEGER(pose)
1327 valid_agent(targ);
1329 // this is basically a copy of PUHL, change that first
1330 if (pose == -1) {
1331 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1332 if (s) {
1333 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1334 targ->carry_points[i] = std::pair<int, int>(x, y);
1336 } else {
1337 // ..Assume a single pose for non-sprite parts.
1338 targ->carry_points[0] = std::pair<int, int>(x, y);
1340 } else {
1341 targ->carry_points[pose] = std::pair<int, int>(x, y);
1346 SETV PUPT (command) pose (integer) x (integer) y (integer)
1347 %status maybe
1348 %pragma variants c2
1350 void caosVM::c_SETV_PUPT() {
1351 c_PUPT();
1355 STPT (command)
1356 %status maybe
1358 Stop the script running in TARG, if any.
1360 void caosVM::c_STPT() {
1361 valid_agent(targ);
1362 targ->stopScript();
1366 DCOR (command) core_on (integer)
1367 %status done
1369 %pragma variants all
1371 Turns the display of the TARG agent's physical core on and off. Gives a general idea of
1372 its size and location (including invisible agents).
1374 void caosVM::c_DCOR() {
1375 VM_PARAM_INTEGER(core_on)
1377 valid_agent(targ);
1378 targ->displaycore = core_on;
1382 MIRA (integer)
1383 %status maybe
1385 Determines whether or not the TARG agent's current sprite is mirrored. Returns 0 or 1.
1387 void caosVM::v_MIRA() {
1388 valid_agent(targ);
1390 // TODO: correct?
1391 SpritePart *p = getCurrentSpritePart();
1392 caos_assert(p);
1394 result.setInt(p->draw_mirrored);
1398 MIRA (command) mirror_on (integer)
1399 %status maybe
1401 Turns mirroring of the TARG agent's current sprite on or off (0 or 1).
1403 void caosVM::c_MIRA() {
1404 VM_PARAM_INTEGER(mirror_on)
1406 valid_agent(targ);
1408 // TODO: what does 'current sprite' mean?
1409 // TODO: correct?
1410 SpritePart *p = getCurrentSpritePart();
1411 caos_assert(p);
1413 p->draw_mirrored = mirror_on;
1417 DISQ (float) other (agent)
1418 %status maybe
1420 Calculates the square of the distance between the centers of the TARG agent and the given
1421 agent.
1423 void caosVM::v_DISQ() {
1424 VM_PARAM_VALIDAGENT(other)
1426 valid_agent(targ);
1428 float x = (targ->x + (targ->getWidth() / 2.0f)) - (other->x + (other->getWidth() / 2.0f));
1429 float y = (targ->y + (targ->getHeight() / 2.0f)) - (other->y + (other->getHeight() / 2.0f));
1431 result.setFloat(x*x + y*y);
1435 ALPH (command) alpha_value (integer) enable (integer)
1436 %status maybe
1438 Sets the degree of alpha blending on the TARG agent, to a value from 0 (solid) to 256
1439 (invisible). The second parameter will turn alpha blending on and off.
1441 void caosVM::c_ALPH() {
1442 VM_PARAM_INTEGER(enable)
1443 VM_PARAM_INTEGER(alpha_value)
1445 if (alpha_value < 0) alpha_value = 0;
1446 else if (alpha_value > 255) alpha_value = 255;
1448 valid_agent(targ);
1450 CompoundAgent *c = dynamic_cast<CompoundAgent *>(targ.get());
1451 if (c && part == -1) {
1452 for (std::vector<CompoundPart *>::iterator i = c->parts.begin(); i != c->parts.end(); i++) {
1453 (*i)->has_alpha = enable;
1454 (*i)->alpha = alpha_value;
1456 } else {
1457 CompoundPart *p = targ->part(part);
1458 caos_assert(p);
1459 p->has_alpha = enable;
1460 p->alpha = alpha_value;
1465 HELD (agent)
1466 %status maybe
1468 Returns the agent currently held by the TARG agent, or a random one if there are more than one.
1470 void caosVM::v_HELD() {
1471 valid_agent(targ);
1473 // TODO: this whole thing perhaps belongs in a virtual function
1474 Vehicle *v = dynamic_cast<Vehicle *>(targ.get());
1475 if (v) {
1476 // TODO: it should be random .. ?
1477 if (v->passengers.size())
1478 result.setAgent(v->passengers[0]);
1479 else
1480 result.setAgent(0);
1481 } else {
1482 result.setAgent(targ->carrying);
1487 GALL (command) spritefile (string) first_image (integer)
1488 %status maybe
1490 Changes the sprite file and first image associated with the TARG agent or current PART.
1492 void caosVM::c_GALL() {
1493 VM_PARAM_INTEGER(first_image)
1494 VM_PARAM_STRING(spritefile)
1496 SpritePart *p = getCurrentSpritePart();
1497 caos_assert(p);
1498 p->changeSprite(spritefile, first_image);
1502 GALL (string)
1503 %status maybe
1505 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.
1507 void caosVM::v_GALL() {
1508 SpritePart *p = getCurrentSpritePart();
1509 if (p)
1510 result.setString(p->getSprite()->getName());
1511 else
1512 result.setString("");
1516 SEEE (integer) first (agent) second (agent)
1517 %status maybe
1519 Returns 1 if the first agent can see the other, or 0 otherwise.
1521 void caosVM::v_SEEE() {
1522 VM_PARAM_VALIDAGENT(second)
1523 VM_PARAM_VALIDAGENT(first)
1525 if (agentIsVisible(first.get(), second.get()))
1526 result.setInt(1);
1527 else
1528 result.setInt(0);
1532 TINT (integer) attribute (integer)
1533 %status stub
1535 Returns the tint value for TARG agent. Pass 1 for red, 2 for blue, 3 for green, 4 for rotation or 5 for swap.
1537 void caosVM::v_TINT() {
1538 VM_PARAM_INTEGER(attribute)
1540 valid_agent(targ);
1541 result.setInt(0); // TODO
1545 TINO (command) red (integer) green (integer) blue (integer) rotation (integer) swap (integer)
1546 %status stub
1548 Works like the TINT command, but only applies the tint to the current frame, and discards the rest.
1550 void caosVM::c_TINO() {
1551 VM_PARAM_INTEGER(swap)
1552 VM_PARAM_INTEGER(rotation)
1553 VM_PARAM_INTEGER(blue)
1554 VM_PARAM_INTEGER(green)
1555 VM_PARAM_INTEGER(red)
1557 // TODO
1561 DROP (command)
1562 %status stub
1563 %pragma variants c1 c2 cv c3 sm
1564 %cost c1,c2 0
1566 Causes the TARG agent to drop what it is carrying in a safe location.
1568 void caosVM::c_DROP() {
1569 valid_agent(targ);
1571 // TODO
1572 // TODO: only creatures in c1 (and c2?)
1575 AgentRef findNextAgent(AgentRef previous, unsigned char family, unsigned char genus, unsigned short species, bool forward) {
1576 if (world.agents.size() == 0) return AgentRef(); // shouldn't happen..
1578 AgentRef firstagent;
1579 bool foundagent = false;
1581 std::list<boost::shared_ptr<Agent> >::iterator i;
1582 if (forward)
1583 i = world.agents.begin();
1584 else {
1585 // TODO: i doubt this works
1586 i = world.agents.end();
1587 i--;
1590 // Loop through all the agents.
1591 while (true) {
1592 Agent *a = i->get();
1593 if (a && (a->family == family || family == 0))
1594 if (a->genus == genus || genus == 0)
1595 if (a->species == species || species == 0) {
1596 if (!firstagent) firstagent = a;
1597 if (foundagent) return AgentRef(a); // This is the agent we want!
1598 if (a == previous) foundagent = true;
1601 // Step through the list. Break if we need to.
1602 if (!forward && i == world.agents.begin()) break;
1603 if (forward) i++; else i--;
1604 if (forward && i == world.agents.end()) break;
1607 // Either we didn't find the previous agent, or we're at the end. Either way, return the first agent found.
1608 return firstagent;
1612 NCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1613 %status maybe
1615 void caosVM::v_NCLS() {
1616 VM_PARAM_INTEGER(species)
1617 VM_PARAM_INTEGER(genus)
1618 VM_PARAM_INTEGER(family)
1619 VM_PARAM_AGENT(previous)
1621 result.setAgent(findNextAgent(previous, family, genus, species, true));
1625 PCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1626 %status maybe
1628 void caosVM::v_PCLS() {
1629 VM_PARAM_INTEGER(species)
1630 VM_PARAM_INTEGER(genus)
1631 VM_PARAM_INTEGER(family)
1632 VM_PARAM_AGENT(previous)
1634 result.setAgent(findNextAgent(previous, family, genus, species, false));
1638 TCOR (integer) topy (float) bottomy (float) leftx (float) rightx (float)
1639 %status stub
1641 void caosVM::v_TCOR() {
1642 VM_PARAM_FLOAT(rightx)
1643 VM_PARAM_FLOAT(leftx)
1644 VM_PARAM_FLOAT(bottomy)
1645 VM_PARAM_FLOAT(topy)
1647 result.setInt(0); // TODO
1651 CORE (command) topy (float) bottomy (float) leftx (float) rightx (float)
1652 %status stub
1654 void caosVM::c_CORE() {
1655 VM_PARAM_FLOAT(rightx)
1656 VM_PARAM_FLOAT(leftx)
1657 VM_PARAM_FLOAT(bottomy)
1658 VM_PARAM_FLOAT(topy)
1660 // TODO
1664 TWIN (agent) source (agent) null_vars (integer)
1665 %status stub
1667 void caosVM::v_TWIN() {
1668 VM_PARAM_INTEGER(null_vars)
1669 VM_PARAM_VALIDAGENT(source)
1671 result.setAgent(0); // TODO
1675 ACTV (variable)
1676 %status maybe
1677 %pragma variants c1 c2
1679 CAOS_LVALUE_TARG_SIMPLE(ACTV, targ->actv);
1682 THRT (variable)
1683 %status maybe
1684 %pragma variants c2
1686 CAOS_LVALUE_TARG_SIMPLE(THRT, targ->thrt);
1689 SIZE (variable)
1690 %status stub
1691 %pragma variants c2
1693 // TODO: stub because this likely == perm
1694 CAOS_LVALUE_TARG_SIMPLE(SIZE, targ->size);
1697 GRAV (variable)
1698 %status stub
1699 %pragma variants c2
1701 // TODO: stub because this likely == falling
1702 CAOS_LVALUE_TARG_SIMPLE(GRAV, targ->grav);
1705 SETV CLS2 (command) family (integer) genus (integer) species (integer)
1706 %status maybe
1707 %pragma variants c2
1709 Creatures 2 command to set the family, genus and species of an agent.
1711 void caosVM::c_SETV_CLS2() {
1712 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
1713 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
1714 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
1716 valid_agent(targ);
1718 targ->setClassifier(family, genus, species);
1722 SLIM (command)
1723 %status stub
1724 %pragma variants c1 c2
1725 %cost c1,c2 0
1727 void caosVM::c_SLIM() {
1728 // TODO: probably shouldn't do anything, but make sure :)
1732 BHVR (command) click (integer) touch (integer)
1733 %status stub
1734 %pragma variants c1 c2
1735 %pragma implementation caosVM::c_BHVR_c2
1736 %cost c1,c2 0
1738 void caosVM::c_BHVR_c2() {
1739 VM_PARAM_INTEGER(touch)
1740 VM_PARAM_INTEGER(click)
1742 valid_agent(targ);
1744 // see Agent::handleClick for details of what these values mean
1745 switch (click) {
1746 // clicks have no effect
1747 case 0: targ->clac[0] = -1; targ->clac[1] = -1; targ->clac[2] = -1; break;
1748 // monostable
1749 case 1: targ->clac[0] = 0; targ->clac[1] = -1; targ->clac[2] = -1; break;
1750 // retriggerable monostable
1751 case 2: targ->clac[0] = 0; targ->clac[1] = 0; targ->clac[2] = -1; break;
1752 // toggle
1753 case 3: targ->clac[0] = 0; targ->clac[1] = 2; targ->clac[2] = -1; break;
1754 // cycle
1755 case 4: targ->clac[0] = 0; targ->clac[1] = 1; targ->clac[2] = 2; break;
1756 default:
1757 // C2, at least, seems to produce random garbage (going off the end of a
1758 // lookup table?) in this situation .. let's not
1759 throw creaturesException(boost::str(boost::format("silly BHVR click value: %d") % click));
1762 // TODO
1766 SETV CLAS (command) identifier (integer)
1767 %status maybe
1768 %pragma variants c1
1770 Set family, genus and species of the target agent. Creatures 1 era command.
1772 void caosVM::c_SETV_CLAS() {
1773 VM_PARAM_INTEGER(identifier)
1775 valid_agent(targ);
1777 targ->setClassifier(
1778 (identifier >> 24) & 0xff,
1779 (identifier >> 16) & 0xff,
1780 (identifier >> 8) & 0xff
1785 LIML (integer)
1786 %status maybe
1787 %pragma variants c1 c2
1789 void caosVM::v_LIML() {
1790 // TODO: is this remotely sane? if so, unstub.
1791 valid_agent(targ);
1793 if (targ->invehicle) {
1794 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1795 result.setInt((int)v->x + v->cabinleft);
1796 } else {
1797 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1799 if (r) result.setInt(r->x_left);
1800 else result.setInt(0);
1805 LIMT (integer)
1806 %status maybe
1807 %pragma variants c1 c2
1809 void caosVM::v_LIMT() {
1810 // TODO: is this remotely sane? if so, unstub.
1811 valid_agent(targ);
1813 if (targ->invehicle) {
1814 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1815 result.setInt((int)v->y + v->cabintop);
1816 } else {
1817 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1819 if (r) result.setInt(r->y_left_ceiling);
1820 else result.setInt(0);
1825 LIMR (integer)
1826 %status maybe
1827 %pragma variants c1 c2
1829 void caosVM::v_LIMR() {
1830 // TODO: is this remotely sane? if so, unstub.
1831 valid_agent(targ);
1833 if (targ->invehicle) {
1834 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1835 result.setInt((int)v->x + v->cabinright);
1836 } else {
1837 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1839 if (r) result.setInt(r->x_right);
1840 else result.setInt(8352); // TODO
1845 LIMB (integer)
1846 %status maybe
1847 %pragma variants c1 c2
1848 %pragma implementation caosVM::v_LIMB_c1
1850 void caosVM::v_LIMB_c1() {
1851 // TODO: is this remotely sane? if so, unstub.
1852 valid_agent(targ);
1854 if (targ->invehicle) {
1855 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1856 result.setInt((int)v->y + v->cabinbottom);
1857 } else {
1858 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1860 if (r) result.setInt(r->y_left_floor);
1861 else result.setInt(1200); // TODO
1866 OBJP (variable)
1867 %status maybe
1868 %pragma variants c1 c2
1870 // TODO: c1 scripts seem to depend on this being from OWNR, but is that always the case?
1871 CAOS_LVALUE_WITH_SIMPLE(OBJP, owner, owner->objp);
1874 XIST (integer) agent (agent)
1875 %status maybe
1876 %pragma variants c2
1878 Undocumented C2 command; returns 1 if specified agent exists, or 0 otherwise (ie, if it is null).
1880 void caosVM::v_XIST() {
1881 VM_PARAM_AGENT(agent)
1883 if (agent.get())
1884 result.setInt(1);
1885 else
1886 result.setInt(0);
1890 SCLE (command) pose (integer) scaleby (integer)
1891 %status stub
1893 void caosVM::c_SCLE() {
1894 VM_PARAM_INTEGER(scaleby)
1895 VM_PARAM_INTEGER(pose)
1897 // TODO
1901 IMGE (command) filename (string)
1902 %status stub
1904 void caosVM::c_IMGE() {
1905 VM_PARAM_STRING(filename)
1907 // TODO
1911 TNTW (command) index (integer)
1912 %status stub
1914 void caosVM::c_TNTW() {
1915 VM_PARAM_INTEGER(index)
1917 // TODO
1921 PRNT (command) pose (integer)
1922 %status stub
1924 void caosVM::c_PRNT() {
1925 VM_PARAM_INTEGER(pose)
1927 // TODO
1931 TCAR (agent)
1932 %status stub
1933 %pragma variants c2
1935 void caosVM::v_TCAR() {
1936 valid_agent(targ);
1938 result.setAgent(0);
1942 EDIT (command)
1943 %status stub
1944 %pragma variants c1 c2
1946 Attach the target agent to the mouse cursor for positioning purposes.
1947 Presently just causes the hand to pick it up.
1949 void caosVM::c_EDIT() {
1950 valid_agent(targ);
1952 world.hand()->addCarried(targ);
1956 FRZN (variable)
1957 %status stub
1958 %pragma variants c2
1960 void caosVM::v_FRZN() {
1961 valid_agent(targ);
1962 caosVar r = targ->frozen ? 1 : 0;
1963 valueStack.push_back(r);
1965 void caosVM::s_FRZN() {
1966 VM_PARAM_VALUE(newvalue)
1967 caos_assert(newvalue.hasInt());
1969 valid_agent(targ);
1970 targ->frozen = newvalue.getInt();
1973 #include "bmpImage.h"
1976 BLCK (command) width (integer) height (integer)
1977 %status maybe
1978 %pragma variants sm
1980 void caosVM::c_BLCK() {
1981 VM_PARAM_INTEGER(height)
1982 VM_PARAM_INTEGER(width)
1984 SpritePart *p = getCurrentSpritePart();
1985 caos_assert(p);
1986 shared_ptr<creaturesImage> i = p->getSprite();
1987 bmpImage *img = dynamic_cast<bmpImage *>(i.get());
1988 caos_assert(img);
1990 img->setBlockSize(width, height);
1993 /* vim: set noet: */