allow any CompoundPart to gain focus, if it canGainFocus()
[openc2e.git] / CompoundAgent.cpp
blob014ab6055c722ebb565dd31b7fb6cdda3a93e319
1 /*
2 * CompoundAgent.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue May 25 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 "CompoundAgent.h"
21 #include "openc2e.h"
22 #include "World.h"
23 #include "Engine.h" // version
24 #include <algorithm> // sort
25 #include <functional> // binary_function
26 #include "caosVM.h" // calculateScriptId
28 // the list of parts is a list of pointers to CompoundPart, so we need a custom sort
29 struct less_part : public std::binary_function<CompoundPart *, CompoundPart *, bool> {
30 bool operator()(CompoundPart *x, CompoundPart *y) { return *x < *y; }
33 void CompoundAgent::addPart(CompoundPart *p) {
34 assert(p);
35 assert(!part(p->id)); // todo: handle better
37 // TODO: we should prbly insert at the right place, not call sort
38 parts.push_back(p);
39 std::sort(parts.begin(), parts.end(), less_part());
41 if (engine.version < 3 && parts.size() == 1) { // adding the first part in c1/c2
42 // TODO: this is zorder hackery - probably the right thing to do, but needs thinking about more
43 unsigned int z = p->zorder;
44 p->zorder = 0;
45 setZOrder(z);
49 void CompoundAgent::delPart(unsigned int id) {
50 caos_assert(id != 0);
52 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) {
53 if ((*x)->id == id) { delete *x; parts.erase(x); return; }
56 throw caosException("delPart got a bad id"); // TODO: handle this exception properly
59 CompoundPart *CompoundAgent::part(unsigned int id) {
60 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) {
61 if ((*x)->id == id) return *x;
63 return 0;
66 CompoundAgent::CompoundAgent(unsigned char _family, unsigned char _genus, unsigned short _species, unsigned int plane,
67 std::string spritefile, unsigned int firstimage, unsigned int imagecount) :
68 Agent(_family, _genus, _species, plane) {
69 // TODO: we ignore image count acos it sucks
70 CompoundPart *p = new DullPart(this, 0, spritefile, firstimage, 0, 0, 0);
71 caos_assert(p);
72 addPart(p);
74 for (unsigned int i = 0; i < 6; i++) {
75 hotspots[i].left = -1; hotspots[i].right = -1; hotspots[i].top = -1;
76 hotspots[i].bottom = -1;
77 hotspotfunctions[i].hotspot = -1;
81 CompoundAgent::CompoundAgent(std::string _spritefile, unsigned int _firstimage, unsigned int _imagecount) : Agent(0, 0, 0, 0) {
82 // TODO: think about plane
84 spritefile = _spritefile;
85 firstimage = _firstimage;
86 imagecount = _imagecount;
88 for (unsigned int i = 0; i < 6; i++) {
89 hotspots[i].left = -1; hotspots[i].right = -1; hotspots[i].top = -1;
90 hotspots[i].bottom = -1;
91 hotspotfunctions[i].hotspot = -1;
95 CompoundAgent::~CompoundAgent() {
96 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) {
97 delete *x;
101 void CompoundAgent::setZOrder(unsigned int plane) {
102 Agent::setZOrder(plane);
103 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) (*x)->zapZOrder();
104 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) (*x)->addZOrder();
107 void CompoundAgent::tick() {
108 if (!paused) {
109 for (std::vector<CompoundPart *>::iterator x = parts.begin(); x != parts.end(); x++) {
110 (*x)->tick();
114 Agent::tick();
117 int CompoundAgent::handleClick(float clickx, float clicky) {
118 if (!activateable()) return -1;
120 if (engine.version > 2) {
121 return Agent::handleClick(clickx, clicky);
124 // the hotspots are relative to us
125 clickx -= x; clicky -= y;
127 // TODO: this whole thing needs more thought/work
129 unsigned int i = 0;
130 if (engine.version == 1) i = 3; // skip C1 creature-only points
131 for (; i < 6; i++) {
132 if (hotspotfunctions[i].hotspot < 0) continue;
133 if (hotspotfunctions[i].hotspot >= 6) continue;
134 unsigned short func;
135 if (engine.version == 1) {
136 // C1: we only check 3/4/5
137 func = calculateScriptId(i - 3);
138 } else {
139 if (hotspotfunctions[i].mask == 1) continue; // creature only
140 func = calculateScriptId(hotspotfunctions[i].message);
143 int j = hotspotfunctions[i].hotspot;
145 if (hotspots[j].left == -1) continue;
146 // TODO: check other items for being -1?
148 if ((clickx >= hotspots[j].left && clickx <= hotspots[j].right) &&
149 (clicky >= hotspots[j].top && clicky <= hotspots[j].bottom)) {
150 return func;
154 return -1;
157 bool CompoundAgent::fireScript(unsigned short event, Agent *from, caosVar one, caosVar two) {
158 // TODO: this is a hack to deal with ACTV on compound agents in c1/c2
159 if (engine.version < 3 && actv.getInt() == event) return false;
161 return Agent::fireScript(event, from, one, two);
164 void CompoundAgent::setHotspotLoc(unsigned int id, int l, int t, int r, int b) {
165 assert(id < 6);
167 hotspots[id].left = l;
168 hotspots[id].top = t;
169 hotspots[id].right = r;
170 hotspots[id].bottom = b;
173 void CompoundAgent::setHotspotFunc(unsigned int id, unsigned int f) {
174 assert(id < 6);
176 hotspotfunctions[id].hotspot = f;
178 // TODO: this tries to make c2 work nicely, necessary?
179 hotspotfunctions[id].mask = 3;
180 if (id < 3)
181 hotspotfunctions[id].message = calculateScriptId(id);
182 else
183 hotspotfunctions[id].message = calculateScriptId(id - 3);
186 void CompoundAgent::setHotspotFuncDetails(unsigned int id, uint16 m, uint8 f) {
187 assert(id < 6);
189 hotspotfunctions[id].message = m;
190 hotspotfunctions[id].mask = f;
193 /* vim: set noet: */