add non-functional c1 Hatchery
[openc2e.git] / caosVM_agent.cpp
blob34c735645eb4938570e17189ce330ac0c4b9fa33
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 if (owner->invehicle)
746 result.setAgent(owner->invehicle);
747 else
748 result.setAgent(owner->carriedby);
752 FMLY (integer)
753 %status maybe
754 %pragma variants c1 c2 cv c3 sm
756 Returns the family of the TARG agent.
758 void caosVM::v_FMLY() {
759 VM_VERIFY_SIZE(0)
760 valid_agent(targ);
761 result.setInt(targ->family);
765 GNUS (integer)
766 %status maybe
767 %pragma variants c1 c2 cv c3 sm
769 Returns the genus of the TARG agent.
771 void caosVM::v_GNUS() {
772 VM_VERIFY_SIZE(0)
773 valid_agent(targ);
774 result.setInt(targ->genus);
778 SPCS (integer)
779 %status maybe
780 %pragma variants c1 c2 cv c3 sm
782 Returns the species of the TARG agent.
784 void caosVM::v_SPCS() {
785 VM_VERIFY_SIZE(0)
786 valid_agent(targ);
787 result.setInt(targ->species);
791 PLNE (integer)
792 %status maybe
794 Returns the plane (z-order) of the TARG agent.
796 void caosVM::v_PLNE() {
797 VM_VERIFY_SIZE(0)
798 valid_agent(targ);
799 result.setInt(targ->getZOrder());
803 PNTR (agent)
804 %status maybe
805 %pragma variants c1 c2 cv c3 sm
807 Returns the pointer agent (the Hand).
809 void caosVM::v_PNTR() {
810 VM_VERIFY_SIZE(0)
811 result.setAgent(world.hand());
814 #include "Engine.h" // for engine.version check, sigh
815 unsigned int calculateScriptId(unsigned int message_id) {
816 // aka, why oh why is this needed? Silly CL.
818 switch (message_id) {
819 case 2: /* deactivate */
820 return 0;
821 case 8: /* hilarious special case to fix c2 airlock */
822 if (engine.version < 3)
823 return 7;
824 else
825 return 8;
826 case 0: /* activate 1 */
827 case 1: /* activate 2 */
828 return message_id + 1;
831 return message_id;
835 MESG WRIT (command) agent (agent) message_id (integer)
836 %status maybe
837 %pragma variants c1 c2 cv c3 sm
838 %cost c1,c2 0
840 Sends a message of type message_id to the given agent. FROM will be set to OWNR unless
841 there is no agent involved in sending the message.
843 void caosVM::c_MESG_WRIT() {
844 VM_VERIFY_SIZE(2)
845 VM_PARAM_INTEGER(message_id)
846 VM_PARAM_VALIDAGENT(agent);
848 agent->queueScript(calculateScriptId(message_id), owner.get());
852 MESG WRT+ (command) agent (agent) message_id (integer) param_1 (anything) param_2 (anything) delay (integer)
853 %status maybe
854 %pragma variants c2 cv c3 sm
856 Sends a message of type message_id to the given agent, much like MESG WRIT, but with the
857 addition of parameters. The message will be sent after waiting the number of ticks set
858 in delay (except doesn't, right now. Delay must be set to zero for now.)
860 void caosVM::c_MESG_WRT() {
861 VM_VERIFY_SIZE(5)
862 VM_PARAM_INTEGER(delay)
863 VM_PARAM_VALUE(param_2)
864 VM_PARAM_VALUE(param_1)
865 VM_PARAM_INTEGER(message_id)
866 VM_PARAM_VALIDAGENT(agent)
868 // I'm not sure how to handle the 'delay'; is it a background delay, or do we actually block for delay ticks?
869 // TODO: fuzzie can't work out how on earth delays work in c2e, someone fixit
871 agent->queueScript(calculateScriptId(message_id), owner.get(), param_1, param_2);
875 TOTL (integer) family (integer) genus (integer) species (integer)
876 %status maybe
877 %pragma variants c1 c2 cv c3 sm
879 Returns the total number of in-game agents matching the given family/genus/species.
881 void caosVM::v_TOTL() {
882 VM_VERIFY_SIZE(3)
883 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
884 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
885 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
887 unsigned int x = 0;
888 for (std::list<boost::shared_ptr<Agent> >::iterator i = world.agents.begin(); i != world.agents.end(); i++) {
889 if (!*i) continue;
890 if ((*i)->family == family || family == 0)
891 if ((*i)->genus == genus || genus == 0)
892 if ((*i)->species == species || species == 0)
893 x++;
895 result.setInt(x);
899 SHOW (command) visibility (integer)
900 %status maybe
902 Sets visibility of the TARG agent to cameras. 0 = invisible, 1 = visible.
904 void caosVM::c_SHOW() {
905 VM_VERIFY_SIZE(1)
906 VM_PARAM_INTEGER(visibility)
907 caos_assert((visibility == 0) || (visibility == 1));
908 valid_agent(targ);
909 targ->visible = visibility;
913 SHOW (integer)
914 %status maybe
916 void caosVM::v_SHOW() {
917 valid_agent(targ);
918 result.setInt(targ->visible ? 1 : 0);
922 POSX (float)
923 %status maybe
924 %pragma variants c2 cv c3 sm
926 Returns the X position of the TARG agent in the world.
928 void caosVM::v_POSX() {
929 VM_VERIFY_SIZE(0)
930 valid_agent(targ);
931 result.setFloat(targ->x + (targ->getWidth() / 2.0f));
935 POSY (float)
936 %status maybe
937 %pragma variants c2 cv c3 sm
939 Returns the Y position of the TARG agent in the world.
941 void caosVM::v_POSY() {
942 VM_VERIFY_SIZE(0)
943 valid_agent(targ);
944 result.setFloat(targ->y + (targ->getHeight() / 2.0f));
948 FRAT (command) framerate (integer)
949 %status maybe
951 Sets the delay between frame changes of the TARG agent or current PART.
952 Must be from 1 to 255, 1 being the normal rate, 2 being half as quickly, and so on.
954 void caosVM::c_FRAT() {
955 VM_VERIFY_SIZE(1)
956 VM_PARAM_INTEGER(framerate)
958 caos_assert(framerate >= 1 && framerate <= 255);
959 valid_agent(targ);
961 SpritePart *p = getCurrentSpritePart();
962 caos_assert(p);
963 p->setFramerate(framerate);
964 p->framedelay = 0;
967 class blockUntilOver : public blockCond {
968 protected:
969 AgentRef targ;
970 int part;
971 public:
972 blockUntilOver(Agent *t, int p) : targ(t), part(p) {}
973 virtual bool operator()() {
974 bool blocking;
975 int fno, animsize;
977 if (!targ) return false;
979 CompoundPart *s = targ->part(part);
980 caos_assert(s);
981 AnimatablePart *p = dynamic_cast<AnimatablePart *>(s);
982 caos_assert(p);
984 fno = p->getFrameNo();
985 animsize = p->animation.size();
987 if (fno + 1 == animsize) blocking = false;
988 else if (animsize == 0) blocking = false;
989 else blocking = true;
990 return blocking;
996 OVER (command)
997 %status maybe
998 %pragma variants c1 c2 cv c3 sm
1000 Waits (blocks the TARG agent) until the animation of the TARG agent or PART is over.
1002 void caosVM::c_OVER() {
1003 valid_agent(targ);
1005 // TODO: The Burrows uses OVER in install script, so fuzzie's making this optional for now, but is this right?
1006 if (owner)
1007 startBlocking(new blockUntilOver(targ, part));
1011 PUHL (command) pose (integer) x (integer) y (integer)
1012 %status maybe
1014 Sets relative x/y coordinates for TARG's pickup point.
1015 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1017 void caosVM::c_PUHL() {
1018 VM_VERIFY_SIZE(3)
1019 VM_PARAM_INTEGER(y)
1020 VM_PARAM_INTEGER(x)
1021 VM_PARAM_INTEGER(pose)
1023 valid_agent(targ);
1025 if (pose == -1) {
1026 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1027 if (s) {
1028 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1029 targ->carried_points[i] = std::pair<int, int>(x, y);
1031 } else {
1032 // ..Assume a single pose for non-sprite parts.
1033 targ->carried_points[0] = std::pair<int, int>(x, y);
1035 } else {
1036 targ->carried_points[pose] = std::pair<int, int>(x, y);
1041 SETV PUHL (command) pose (integer) x (integer) y (integer)
1042 %status maybe
1043 %pragma variants c2
1045 Sets relative x/y coordinates for TARG's pickup point.
1046 Pose is -1 for all poses, or a pose relative to the first image specified in NEW: (not BASE).
1048 void caosVM::c_SETV_PUHL() {
1049 c_PUHL();
1053 PUHL (integer) pose (integer) x_or_y (integer)
1054 %status maybe
1056 Returns the coordinate for TARG's pickup point. x_or_y should be 1 for x, or 2 for y.
1058 void caosVM::v_PUHL() {
1059 VM_PARAM_INTEGER(x_or_y)
1060 VM_PARAM_INTEGER(pose)
1062 valid_agent(targ);
1064 // TODO: this creates the variable if it doesn't exist yet, correct behaviour?
1065 if (x_or_y == 1) {
1066 result.setInt(targ->carried_points[pose].first);
1067 } else {
1068 caos_assert(x_or_y == 2);
1069 result.setInt(targ->carried_points[pose].second);
1074 POSL (float)
1075 %status maybe
1076 %pragma variants c1 c2 cv c3 sm
1078 Returns the position of the left side of TARG's bounding box.
1080 void caosVM::v_POSL() {
1081 VM_VERIFY_SIZE(0)
1083 valid_agent(targ);
1084 result.setFloat(targ->x);
1088 POST (float)
1089 %status maybe
1090 %pragma variants c1 c2 cv c3 sm
1092 Returns the position of the top side of TARG's bounding box.
1094 void caosVM::v_POST() {
1095 VM_VERIFY_SIZE(0)
1097 valid_agent(targ);
1098 result.setFloat(targ->y);
1102 POSR (float)
1103 %status maybe
1104 %pragma variants c1 c2 cv c3 sm
1106 Returns the position of the right side of TARG's bounding box.
1108 void caosVM::v_POSR() {
1109 VM_VERIFY_SIZE(0)
1111 valid_agent(targ);
1112 result.setFloat(targ->x + targ->getWidth());
1116 POSB (float)
1117 %status maybe
1118 %pragma variants c1 c2 cv c3 sm
1120 Returns the position of the bottom side of TARG's bounding box.
1122 void caosVM::v_POSB() {
1123 VM_VERIFY_SIZE(0)
1125 valid_agent(targ);
1126 result.setFloat(targ->y + targ->getHeight());
1130 WDTH (integer)
1131 %status maybe
1132 %pragma variants c1 c2 cv c3 sm
1134 Returns the TARG agent's width.
1136 void caosVM::v_WDTH() {
1137 VM_VERIFY_SIZE(0)
1139 valid_agent(targ);
1140 result.setInt(targ->getWidth());
1144 PLNE (command) depth (integer)
1145 %status maybe
1147 Sets the plane (the z-order) of the TARG agent. Higher values are closer to the camera.
1149 void caosVM::c_PLNE() {
1150 VM_VERIFY_SIZE(1)
1151 VM_PARAM_INTEGER(depth)
1153 valid_agent(targ);
1154 targ->setZOrder(depth);
1158 TINT (command) red_tint (integer) green_tint (integer) blue_tint (integer) rotation (integer) swap (integer)
1159 %status maybe
1161 Sets the tinting of the TARG agent to the given red, blue, and green values.
1163 void caosVM::c_TINT() {
1164 VM_VERIFY_SIZE(5)
1165 VM_PARAM_INTEGER(swap)
1166 VM_PARAM_INTEGER(rotation)
1167 VM_PARAM_INTEGER(blue_tint)
1168 VM_PARAM_INTEGER(green_tint)
1169 VM_PARAM_INTEGER(red_tint)
1171 caos_assert(red_tint >= 0 && red_tint <= 256);
1172 caos_assert(green_tint >= 0 && green_tint <= 256);
1173 caos_assert(blue_tint >= 0 && blue_tint <= 256);
1174 caos_assert(swap >= 0 && swap <= 256);
1175 caos_assert(rotation >= 0 && rotation <= 256);
1177 SpritePart *p = getCurrentSpritePart();
1178 caos_assert(p);
1179 p->tint(red_tint, green_tint, blue_tint, rotation, swap);
1183 RNGE (command) distance (float)
1184 %status maybe
1186 Sets the TARG agent's range (i.e., the distance it can see and hear).
1188 void caosVM::c_RNGE() {
1189 VM_VERIFY_SIZE(1)
1190 VM_PARAM_FLOAT(distance)
1192 valid_agent(targ);
1193 targ->range = distance;
1197 RNGE (integer)
1198 %status maybe
1200 Returns the TARG agent's range.
1202 void caosVM::v_RNGE() {
1203 VM_VERIFY_SIZE(0)
1204 valid_agent(targ);
1205 result.setFloat(targ->range.getFloat());
1209 RNGE (variable)
1210 %status maybe
1211 %pragma variants c2
1212 %pragma implementation caosVM::v_RNGE_c2
1214 Returns the TARG agent's range.
1216 CAOS_LVALUE_TARG_SIMPLE(RNGE_c2, targ->range);
1219 TRAN (integer) x (integer) y (integer)
1220 %status maybe
1222 Tests if the pixel at (x,y) on the TARG agent is transparent.
1223 Returns 0 or 1.
1225 void caosVM::v_TRAN() {
1226 VM_VERIFY_SIZE(2)
1227 VM_PARAM_INTEGER(y)
1228 VM_PARAM_INTEGER(x)
1230 valid_agent(targ);
1231 CompoundPart *s = targ->part(0); assert(s);
1232 SpritePart *p = dynamic_cast<SpritePart *>(s);
1233 caos_assert(p);
1234 caos_assert(x >= 0 && x <= (int)p->getWidth());
1235 caos_assert(y >= 0 && y <= (int)p->getHeight());
1236 if (p->transparentAt(x, y))
1237 result.setInt(1);
1238 else
1239 result.setInt(0);
1243 TRAN (command) transparency (integer) part_no (integer)
1244 %status maybe
1246 Sets the TARG agent's behaviour with regard to transparency. If set to 1, invisible
1247 parts of the agent can't be clicked. If 0, anywhere on the agent (including transparent
1248 parts) can be clicked.
1250 void caosVM::c_TRAN() {
1251 VM_VERIFY_SIZE(2)
1252 VM_PARAM_INTEGER(part_no)
1253 VM_PARAM_INTEGER(transparency)
1255 valid_agent(targ);
1256 // TODO: handle -1?
1257 CompoundPart *s = targ->part(part_no);
1258 caos_assert(s);
1259 SpritePart *p = dynamic_cast<SpritePart *>(s);
1260 caos_assert(p);
1261 p->is_transparent = transparency;
1265 HGHT (integer)
1266 %status maybe
1267 %pragma variants c1 c2 cv c3 sm
1269 Returns the TARG agent's height.
1271 void caosVM::v_HGHT() {
1272 VM_VERIFY_SIZE(0)
1273 valid_agent(targ);
1275 result.setInt(targ->getHeight());
1279 HAND (string)
1280 %status maybe
1282 Returns the name of the Hand; default is 'hand'.
1284 void caosVM::v_HAND() {
1285 VM_VERIFY_SIZE(0)
1287 result.setString(world.hand()->name);
1291 HAND (command) name (string)
1292 %status maybe
1294 Sets the name of the Hand.
1296 void caosVM::c_HAND() {
1297 VM_VERIFY_SIZE(1)
1298 VM_PARAM_STRING(name)
1300 world.hand()->name = name;
1304 TICK (integer)
1305 %status maybe
1306 %pragma variants c2 cv c3 sm
1308 Return the agent timer tick rate of the TARG agent.
1310 void caosVM::v_TICK() {
1311 VM_VERIFY_SIZE(0)
1313 valid_agent(targ);
1314 result.setInt(targ->timerrate);
1318 PUPT (command) pose (integer) x (integer) y (integer)
1319 %status maybe
1321 Sets relative x/y coordinates for the location in the world where the TARG agent picks up
1322 objects. The pose is relative to the first image set in NEW: (not BASE).
1324 void caosVM::c_PUPT() {
1325 VM_VERIFY_SIZE(3)
1326 VM_PARAM_INTEGER(y)
1327 VM_PARAM_INTEGER(x)
1328 VM_PARAM_INTEGER(pose)
1330 valid_agent(targ);
1332 // this is basically a copy of PUHL, change that first
1333 if (pose == -1) {
1334 SpritePart *s = dynamic_cast<SpritePart *>(targ->part(0));
1335 if (s) {
1336 for (unsigned int i = 0; i < (s->getFirstImg() + s->getSprite()->numframes()); i++) {
1337 targ->carry_points[i] = std::pair<int, int>(x, y);
1339 } else {
1340 // ..Assume a single pose for non-sprite parts.
1341 targ->carry_points[0] = std::pair<int, int>(x, y);
1343 } else {
1344 targ->carry_points[pose] = std::pair<int, int>(x, y);
1349 SETV PUPT (command) pose (integer) x (integer) y (integer)
1350 %status maybe
1351 %pragma variants c2
1353 void caosVM::c_SETV_PUPT() {
1354 c_PUPT();
1358 STPT (command)
1359 %status maybe
1361 Stop the script running in TARG, if any.
1363 void caosVM::c_STPT() {
1364 valid_agent(targ);
1365 targ->stopScript();
1369 DCOR (command) core_on (integer)
1370 %status done
1372 %pragma variants all
1374 Turns the display of the TARG agent's physical core on and off. Gives a general idea of
1375 its size and location (including invisible agents).
1377 void caosVM::c_DCOR() {
1378 VM_PARAM_INTEGER(core_on)
1380 valid_agent(targ);
1381 targ->displaycore = core_on;
1385 MIRA (integer)
1386 %status maybe
1388 Determines whether or not the TARG agent's current sprite is mirrored. Returns 0 or 1.
1390 void caosVM::v_MIRA() {
1391 valid_agent(targ);
1393 // TODO: correct?
1394 SpritePart *p = getCurrentSpritePart();
1395 caos_assert(p);
1397 result.setInt(p->draw_mirrored);
1401 MIRA (command) mirror_on (integer)
1402 %status maybe
1404 Turns mirroring of the TARG agent's current sprite on or off (0 or 1).
1406 void caosVM::c_MIRA() {
1407 VM_PARAM_INTEGER(mirror_on)
1409 valid_agent(targ);
1411 // TODO: what does 'current sprite' mean?
1412 // TODO: correct?
1413 SpritePart *p = getCurrentSpritePart();
1414 caos_assert(p);
1416 p->draw_mirrored = mirror_on;
1420 DISQ (float) other (agent)
1421 %status maybe
1423 Calculates the square of the distance between the centers of the TARG agent and the given
1424 agent.
1426 void caosVM::v_DISQ() {
1427 VM_PARAM_VALIDAGENT(other)
1429 valid_agent(targ);
1431 float x = (targ->x + (targ->getWidth() / 2.0f)) - (other->x + (other->getWidth() / 2.0f));
1432 float y = (targ->y + (targ->getHeight() / 2.0f)) - (other->y + (other->getHeight() / 2.0f));
1434 result.setFloat(x*x + y*y);
1438 ALPH (command) alpha_value (integer) enable (integer)
1439 %status maybe
1441 Sets the degree of alpha blending on the TARG agent, to a value from 0 (solid) to 256
1442 (invisible). The second parameter will turn alpha blending on and off.
1444 void caosVM::c_ALPH() {
1445 VM_PARAM_INTEGER(enable)
1446 VM_PARAM_INTEGER(alpha_value)
1448 if (alpha_value < 0) alpha_value = 0;
1449 else if (alpha_value > 255) alpha_value = 255;
1451 valid_agent(targ);
1453 CompoundAgent *c = dynamic_cast<CompoundAgent *>(targ.get());
1454 if (c && part == -1) {
1455 for (std::vector<CompoundPart *>::iterator i = c->parts.begin(); i != c->parts.end(); i++) {
1456 (*i)->has_alpha = enable;
1457 (*i)->alpha = alpha_value;
1459 } else {
1460 CompoundPart *p = targ->part(part);
1461 caos_assert(p);
1462 p->has_alpha = enable;
1463 p->alpha = alpha_value;
1468 HELD (agent)
1469 %status maybe
1471 Returns the agent currently held by the TARG agent, or a random one if there are more than one.
1473 void caosVM::v_HELD() {
1474 valid_agent(targ);
1476 // TODO: this whole thing perhaps belongs in a virtual function
1477 Vehicle *v = dynamic_cast<Vehicle *>(targ.get());
1478 if (v) {
1479 // TODO: it should be random .. ?
1480 if (v->passengers.size())
1481 result.setAgent(v->passengers[0]);
1482 else
1483 result.setAgent(0);
1484 } else {
1485 result.setAgent(targ->carrying);
1490 GALL (command) spritefile (string) first_image (integer)
1491 %status maybe
1493 Changes the sprite file and first image associated with the TARG agent or current PART.
1495 void caosVM::c_GALL() {
1496 VM_PARAM_INTEGER(first_image)
1497 VM_PARAM_STRING(spritefile)
1499 SpritePart *p = getCurrentSpritePart();
1500 caos_assert(p);
1501 p->changeSprite(spritefile, first_image);
1505 GALL (string)
1506 %status maybe
1508 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.
1510 void caosVM::v_GALL() {
1511 SpritePart *p = getCurrentSpritePart();
1512 if (p)
1513 result.setString(p->getSprite()->getName());
1514 else
1515 result.setString("");
1519 SEEE (integer) first (agent) second (agent)
1520 %status maybe
1522 Returns 1 if the first agent can see the other, or 0 otherwise.
1524 void caosVM::v_SEEE() {
1525 VM_PARAM_VALIDAGENT(second)
1526 VM_PARAM_VALIDAGENT(first)
1528 if (agentIsVisible(first.get(), second.get()))
1529 result.setInt(1);
1530 else
1531 result.setInt(0);
1535 TINT (integer) attribute (integer)
1536 %status stub
1538 Returns the tint value for TARG agent. Pass 1 for red, 2 for blue, 3 for green, 4 for rotation or 5 for swap.
1540 void caosVM::v_TINT() {
1541 VM_PARAM_INTEGER(attribute)
1543 valid_agent(targ);
1544 result.setInt(0); // TODO
1548 TINO (command) red (integer) green (integer) blue (integer) rotation (integer) swap (integer)
1549 %status stub
1551 Works like the TINT command, but only applies the tint to the current frame, and discards the rest.
1553 void caosVM::c_TINO() {
1554 VM_PARAM_INTEGER(swap)
1555 VM_PARAM_INTEGER(rotation)
1556 VM_PARAM_INTEGER(blue)
1557 VM_PARAM_INTEGER(green)
1558 VM_PARAM_INTEGER(red)
1560 // TODO
1564 DROP (command)
1565 %status stub
1566 %pragma variants c1 c2 cv c3 sm
1567 %cost c1,c2 0
1569 Causes the TARG agent to drop what it is carrying in a safe location.
1571 void caosVM::c_DROP() {
1572 valid_agent(targ);
1574 // TODO
1575 // TODO: only creatures in c1 (and c2?)
1578 AgentRef findNextAgent(AgentRef previous, unsigned char family, unsigned char genus, unsigned short species, bool forward) {
1579 if (world.agents.size() == 0) return AgentRef(); // shouldn't happen..
1581 AgentRef firstagent;
1582 bool foundagent = false;
1584 std::list<boost::shared_ptr<Agent> >::iterator i;
1585 if (forward)
1586 i = world.agents.begin();
1587 else {
1588 // TODO: i doubt this works
1589 i = world.agents.end();
1590 i--;
1593 // Loop through all the agents.
1594 while (true) {
1595 Agent *a = i->get();
1596 if (a && (a->family == family || family == 0))
1597 if (a->genus == genus || genus == 0)
1598 if (a->species == species || species == 0) {
1599 if (!firstagent) firstagent = a;
1600 if (foundagent) return AgentRef(a); // This is the agent we want!
1601 if (a == previous) foundagent = true;
1604 // Step through the list. Break if we need to.
1605 if (!forward && i == world.agents.begin()) break;
1606 if (forward) i++; else i--;
1607 if (forward && i == world.agents.end()) break;
1610 // Either we didn't find the previous agent, or we're at the end. Either way, return the first agent found.
1611 return firstagent;
1615 NCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1616 %status maybe
1618 void caosVM::v_NCLS() {
1619 VM_PARAM_INTEGER(species)
1620 VM_PARAM_INTEGER(genus)
1621 VM_PARAM_INTEGER(family)
1622 VM_PARAM_AGENT(previous)
1624 result.setAgent(findNextAgent(previous, family, genus, species, true));
1628 PCLS (agent) previous (agent) family (integer) genus (integer) species (integer)
1629 %status maybe
1631 void caosVM::v_PCLS() {
1632 VM_PARAM_INTEGER(species)
1633 VM_PARAM_INTEGER(genus)
1634 VM_PARAM_INTEGER(family)
1635 VM_PARAM_AGENT(previous)
1637 result.setAgent(findNextAgent(previous, family, genus, species, false));
1641 TCOR (integer) topy (float) bottomy (float) leftx (float) rightx (float)
1642 %status stub
1644 void caosVM::v_TCOR() {
1645 VM_PARAM_FLOAT(rightx)
1646 VM_PARAM_FLOAT(leftx)
1647 VM_PARAM_FLOAT(bottomy)
1648 VM_PARAM_FLOAT(topy)
1650 result.setInt(0); // TODO
1654 CORE (command) topy (float) bottomy (float) leftx (float) rightx (float)
1655 %status stub
1657 void caosVM::c_CORE() {
1658 VM_PARAM_FLOAT(rightx)
1659 VM_PARAM_FLOAT(leftx)
1660 VM_PARAM_FLOAT(bottomy)
1661 VM_PARAM_FLOAT(topy)
1663 // TODO
1667 TWIN (agent) source (agent) null_vars (integer)
1668 %status stub
1670 void caosVM::v_TWIN() {
1671 VM_PARAM_INTEGER(null_vars)
1672 VM_PARAM_VALIDAGENT(source)
1674 result.setAgent(0); // TODO
1678 ACTV (variable)
1679 %status maybe
1680 %pragma variants c1 c2
1682 CAOS_LVALUE_TARG_SIMPLE(ACTV, targ->actv);
1685 THRT (variable)
1686 %status maybe
1687 %pragma variants c2
1689 CAOS_LVALUE_TARG_SIMPLE(THRT, targ->thrt);
1692 SIZE (variable)
1693 %status stub
1694 %pragma variants c2
1696 // TODO: stub because this likely == perm
1697 CAOS_LVALUE_TARG_SIMPLE(SIZE, targ->size);
1700 GRAV (variable)
1701 %status stub
1702 %pragma variants c2
1704 // TODO: stub because this likely == falling
1705 CAOS_LVALUE_TARG_SIMPLE(GRAV, targ->grav);
1708 SETV CLS2 (command) family (integer) genus (integer) species (integer)
1709 %status maybe
1710 %pragma variants c2
1712 Creatures 2 command to set the family, genus and species of an agent.
1714 void caosVM::c_SETV_CLS2() {
1715 VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
1716 VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
1717 VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);
1719 valid_agent(targ);
1721 targ->setClassifier(family, genus, species);
1725 SLIM (command)
1726 %status stub
1727 %pragma variants c1 c2
1728 %cost c1,c2 0
1730 void caosVM::c_SLIM() {
1731 // TODO: probably shouldn't do anything, but make sure :)
1735 BHVR (command) click (integer) touch (integer)
1736 %status stub
1737 %pragma variants c1 c2
1738 %pragma implementation caosVM::c_BHVR_c2
1739 %cost c1,c2 0
1741 void caosVM::c_BHVR_c2() {
1742 VM_PARAM_INTEGER(touch)
1743 VM_PARAM_INTEGER(click)
1745 valid_agent(targ);
1747 // see Agent::handleClick for details of what these values mean
1748 switch (click) {
1749 // clicks have no effect
1750 case 0: targ->clac[0] = -1; targ->clac[1] = -1; targ->clac[2] = -1; break;
1751 // monostable
1752 case 1: targ->clac[0] = 0; targ->clac[1] = -1; targ->clac[2] = -1; break;
1753 // retriggerable monostable
1754 case 2: targ->clac[0] = 0; targ->clac[1] = 0; targ->clac[2] = -1; break;
1755 // toggle
1756 case 3: targ->clac[0] = 0; targ->clac[1] = 2; targ->clac[2] = -1; break;
1757 // cycle
1758 case 4: targ->clac[0] = 0; targ->clac[1] = 1; targ->clac[2] = 2; break;
1759 default:
1760 // C2, at least, seems to produce random garbage (going off the end of a
1761 // lookup table?) in this situation .. let's not
1762 throw creaturesException(boost::str(boost::format("silly BHVR click value: %d") % click));
1765 // TODO
1769 SETV CLAS (command) identifier (integer)
1770 %status maybe
1771 %pragma variants c1
1773 Set family, genus and species of the target agent. Creatures 1 era command.
1775 void caosVM::c_SETV_CLAS() {
1776 VM_PARAM_INTEGER(identifier)
1778 valid_agent(targ);
1780 targ->setClassifier(
1781 (identifier >> 24) & 0xff,
1782 (identifier >> 16) & 0xff,
1783 (identifier >> 8) & 0xff
1788 LIML (integer)
1789 %status maybe
1790 %pragma variants c1 c2
1792 void caosVM::v_LIML() {
1793 // TODO: is this remotely sane? if so, unstub.
1794 valid_agent(targ);
1796 if (targ->invehicle) {
1797 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1798 result.setInt((int)v->x + v->cabinleft);
1799 } else {
1800 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1802 if (r) result.setInt(r->x_left);
1803 else result.setInt(0);
1808 LIMT (integer)
1809 %status maybe
1810 %pragma variants c1 c2
1812 void caosVM::v_LIMT() {
1813 // TODO: is this remotely sane? if so, unstub.
1814 valid_agent(targ);
1816 if (targ->invehicle) {
1817 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1818 result.setInt((int)v->y + v->cabintop);
1819 } else {
1820 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1822 if (r) result.setInt(r->y_left_ceiling);
1823 else result.setInt(0);
1828 LIMR (integer)
1829 %status maybe
1830 %pragma variants c1 c2
1832 void caosVM::v_LIMR() {
1833 // TODO: is this remotely sane? if so, unstub.
1834 valid_agent(targ);
1836 if (targ->invehicle) {
1837 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1838 result.setInt((int)v->x + v->cabinright);
1839 } else {
1840 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1842 if (r) result.setInt(r->x_right);
1843 else result.setInt(8352); // TODO
1848 LIMB (integer)
1849 %status maybe
1850 %pragma variants c1 c2
1851 %pragma implementation caosVM::v_LIMB_c1
1853 void caosVM::v_LIMB_c1() {
1854 // TODO: is this remotely sane? if so, unstub.
1855 valid_agent(targ);
1857 if (targ->invehicle) {
1858 Vehicle *v = dynamic_cast<Vehicle *>(targ->invehicle.get()); assert(v);
1859 result.setInt((int)v->y + v->cabinbottom);
1860 } else {
1861 shared_ptr<Room> r = world.map.roomAt(targ->x + (targ->getWidth() / 2.0f), targ->y + (targ->getHeight() / 2.0f));
1863 if (r) result.setInt(r->y_left_floor);
1864 else result.setInt(1200); // TODO
1869 OBJP (variable)
1870 %status maybe
1871 %pragma variants c1 c2
1873 // TODO: c1 scripts seem to depend on this being from OWNR, but is that always the case?
1874 CAOS_LVALUE_WITH_SIMPLE(OBJP, owner, owner->objp);
1877 XIST (integer) agent (agent)
1878 %status maybe
1879 %pragma variants c2
1881 Undocumented C2 command; returns 1 if specified agent exists, or 0 otherwise (ie, if it is null).
1883 void caosVM::v_XIST() {
1884 VM_PARAM_AGENT(agent)
1886 if (agent.get())
1887 result.setInt(1);
1888 else
1889 result.setInt(0);
1893 SCLE (command) pose (integer) scaleby (integer)
1894 %status stub
1896 void caosVM::c_SCLE() {
1897 VM_PARAM_INTEGER(scaleby)
1898 VM_PARAM_INTEGER(pose)
1900 // TODO
1904 IMGE (command) filename (string)
1905 %status stub
1907 void caosVM::c_IMGE() {
1908 VM_PARAM_STRING(filename)
1910 // TODO
1914 TNTW (command) index (integer)
1915 %status stub
1917 void caosVM::c_TNTW() {
1918 VM_PARAM_INTEGER(index)
1920 // TODO
1924 PRNT (command) pose (integer)
1925 %status stub
1927 void caosVM::c_PRNT() {
1928 VM_PARAM_INTEGER(pose)
1930 // TODO
1934 TCAR (agent)
1935 %status maybe
1936 %pragma variants c2
1938 void caosVM::v_TCAR() {
1939 valid_agent(targ);
1941 if (targ->invehicle)
1942 result.setAgent(targ->invehicle);
1943 else
1944 result.setAgent(targ->carriedby);
1948 EDIT (command)
1949 %status stub
1950 %pragma variants c1 c2
1952 Attach the target agent to the mouse cursor for positioning purposes.
1954 void caosVM::c_EDIT() {
1955 valid_agent(targ);
1957 world.hand()->editAgent = targ;
1961 FRZN (variable)
1962 %status stub
1963 %pragma variants c2
1965 void caosVM::v_FRZN() {
1966 valid_agent(targ);
1967 caosVar r = targ->frozen ? 1 : 0;
1968 valueStack.push_back(r);
1970 void caosVM::s_FRZN() {
1971 VM_PARAM_VALUE(newvalue)
1972 caos_assert(newvalue.hasInt());
1974 valid_agent(targ);
1975 targ->frozen = newvalue.getInt();
1978 #include "bmpImage.h"
1981 BLCK (command) width (integer) height (integer)
1982 %status maybe
1983 %pragma variants sm
1985 void caosVM::c_BLCK() {
1986 VM_PARAM_INTEGER(height)
1987 VM_PARAM_INTEGER(width)
1989 SpritePart *p = getCurrentSpritePart();
1990 caos_assert(p);
1991 shared_ptr<creaturesImage> i = p->getSprite();
1992 bmpImage *img = dynamic_cast<bmpImage *>(i.get());
1993 caos_assert(img);
1995 img->setBlockSize(width, height);
1998 /* vim: set noet: */