check activateable() before allowing clicks (oops)
[openc2e.git] / PointerAgent.cpp
blob9a9941625f24c791bd34ab83c7b94068f770dcd2
1 /*
2 * PointerAgent.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue Aug 30 2005.
6 * Copyright (c) 2005 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 "PointerAgent.h"
21 #include "openc2e.h"
22 #include "World.h"
23 #include "Engine.h"
24 #include "caosVM.h"
25 #include "Room.h"
27 // TODO: change imagecount?
28 PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
29 name = "hand";
30 handle_events = true;
31 holdingWire = 0;
32 wireOriginID = 0;
33 // TODO: verify attributes on the pointer in c2e
34 attr.setInt(256); // camera shy
37 void PointerAgent::finishInit() {
38 Agent::finishInit();
40 // float relative to main camera
41 attr.setInt(attr.getInt() & 32);
42 floatSetup();
45 // TODO: this should have a queueScript equiv too
46 void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
47 assert(src); // TODO: I /think/ this should only be called by the engine..
48 shared_ptr<script> s = src->findScript(event);
49 if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
50 s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
52 if (!s) return;
53 if (!vm) vm = world.getVM(this);
54 if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
55 vm->setTarg(this);
56 zotstack();
60 void PointerAgent::physicsTick() {
61 // TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
64 void PointerAgent::kill() {
65 // pointer agent isn't killable
68 void PointerAgent::handleEvent(SomeEvent &event) {
69 if (event.type == eventmousemove) {
70 moveTo(event.x + world.camera.getX(), event.y + world.camera.getY());
71 velx.setInt(event.xrel * 4);
72 vely.setInt(event.yrel * 4);
74 // middle mouse button scrolling
75 if (event.button & buttonmiddle)
76 world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
77 } else if (!handle_events) {
78 /* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
79 return;
80 } else if (event.type == eventmousebuttondown) {
81 // do our custom handling
82 if (event.button == buttonleft) {
83 CompoundPart *a = world.partAt(x, y);
84 if (a /* && a->canActivate() */) { // TODO
85 Agent* parent = a->getParent();
87 int eve = -1;
89 bool foundport = false;
90 if (engine.version > 2) {
91 for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
92 i != parent->outports.end(); i++) {
93 // TODO: 4 is a magic number i pulled out of nooooowhere
94 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
95 foundport = true;
96 if (holdingWire == 2) {
97 parent->join(i->first, wireOriginAgent, wireOriginID);
98 holdingWire = 0;
99 eve = 111;
100 } else if (holdingWire == 0) {
101 eve = 110;
102 holdingWire = 1;
103 wireOriginAgent = parent;
104 wireOriginID = i->first;
106 break;
109 if (!foundport) {
110 for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
111 i != parent->inports.end(); i++) {
112 // TODO: 4 is a magic number i pulled out of nooooowhere
113 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
114 foundport = true;
115 if (holdingWire == 1) {
116 if (i->second->source) {
117 eve = 114;
118 } else {
119 wireOriginAgent->join(wireOriginID, parent, i->first);
120 holdingWire = 0;
121 eve = 111;
123 } else if (holdingWire == 0) {
124 if (i->second->source) {
125 eve = 112;
126 holdingWire = 1;
127 wireOriginAgent = i->second->source;
128 wireOriginID = i->second->sourceid;
129 i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
130 i->second->source.clear();
131 } else {
132 eve = 110;
133 holdingWire = 2;
134 wireOriginAgent = parent;
135 wireOriginID = i->first;
138 break;
144 if (!foundport) {
145 if (holdingWire) {
146 holdingWire = 0;
147 eve = 113;
148 } else {
149 // if the agent isn't paused, tell it to handle a click
150 int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
151 if (scriptid != -1) {
152 // fire the script
153 // _p1_ is id of part for button clicks, according to Edynn code
154 // TODO: should _p1_ always be set? :)
155 if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);
157 // annoyingly queueScript doesn't reliably tell us if it did anything useful.
158 // TODO: work out the mess which is queueScript's return values etc
159 if (!parent->findScript(scriptid)) return;
161 // fire the associated pointer script too, if necessary
162 // TODO: fuzzie has no idea if this code is remotely correct
163 if (engine.version < 3) {
164 eve = 50;
165 } else {
166 eve = 101; // Pointer Activate 1
168 switch (scriptid) {
169 case 0: eve += 2; break; // deactivate
170 case 1: break; // activate 1
171 case 2: eve += 1; break; // activate 2
172 default: return;
178 if (eve != -1) firePointerScript(eve, a->getParent());
179 } else if (engine.version > 2) {
180 if (holdingWire) {
181 holdingWire = 0;
182 queueScript(113, 0);
183 } else {
184 queueScript(116, 0); // Pointer Clicked Background
187 } else if (event.button == buttonright) {
188 if (world.paused) return; // TODO: wrong?
190 // picking up and dropping are implictly handled by the scripts (well,
191 // messages) 4 and 5 TODO: check if this is correct behaviour, one issue
192 // is that this isn't instant, another is the messages might only be
193 // fired in c2e when you use MESG WRIT, in which case we'll need to
194 // manually set carrying to NULL and a here, respectively - fuzzie
195 if (carrying) {
196 // TODO: c1 support - these attributes are invalid for c1
197 if (!carrying->suffercollisions() || (carrying->validInRoomSystem() || engine.version == 1)) {
198 carrying->queueScript(5, this); // drop
200 int eve; if (engine.version < 3) eve = 54; else eve = 105;
201 firePointerScript(eve, carrying); // Pointer Drop
203 // TODO: is this the correct check?
204 if (carrying->sufferphysics() && carrying->suffercollisions()) {
205 // TODO: do this in the pointer agent?
206 carrying->velx.setFloat(velx.getFloat());
207 carrying->vely.setFloat(vely.getFloat());
209 } else {
210 // TODO: some kind of "fail to drop" animation/sound?
212 } else {
213 Agent *a = world.agentAt(x, y, false, true);
214 if (a) {
215 a->queueScript(4, this); // pickup
217 int eve; if (engine.version < 3) eve = 53; else eve = 104;
218 firePointerScript(eve, a); // Pointer Pickup
221 } else if (event.button == buttonmiddle) {
222 std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(event.x + world.camera.getX(), event.y + world.camera.getY());
223 if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
224 Agent *a = world.agentAt(event.x + world.camera.getX(), event.y + world.camera.getY(), true);
225 if (a)
226 std::cout << "Agent under mouse is " << a->identify();
227 else
228 std::cout << "No agent under cursor";
229 std::cout << std::endl;
234 /* vim: set noet: */