add some hacky code to allow passing sfc files with -b
[openc2e.git] / PointerAgent.cpp
blob26581138c7bd7c172eb345ed1f20f830a1828d3d
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::setHotspot(int x, int y) {
69 hotspotx = x;
70 hotspoty = y;
73 void PointerAgent::handleEvent(SomeEvent &event) {
74 int x = pointerX(), y = pointerY();
76 if (event.type == eventmousemove) {
77 moveTo(event.x + world.camera.getX() - hotspotx, event.y + world.camera.getY() - hotspoty);
78 velx.setInt(event.xrel * 4);
79 vely.setInt(event.yrel * 4);
81 // middle mouse button scrolling
82 if (event.button & buttonmiddle)
83 world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
84 } else if (!handle_events) {
85 /* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
86 return;
87 } else if (event.type == eventmousebuttondown) {
88 // do our custom handling
89 if (event.button == buttonleft) {
90 CompoundPart *a = world.partAt(x, y);
91 if (a /* && a->canActivate() */) { // TODO
92 Agent* parent = a->getParent();
94 int eve = -1;
96 bool foundport = false;
97 if (engine.version > 2) {
98 for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
99 i != parent->outports.end(); i++) {
100 // TODO: 4 is a magic number i pulled out of nooooowhere
101 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
102 foundport = true;
103 if (holdingWire == 2) {
104 parent->join(i->first, wireOriginAgent, wireOriginID);
105 holdingWire = 0;
106 eve = 111;
107 } else if (holdingWire == 0) {
108 eve = 110;
109 holdingWire = 1;
110 wireOriginAgent = parent;
111 wireOriginID = i->first;
113 break;
116 if (!foundport) {
117 for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
118 i != parent->inports.end(); i++) {
119 // TODO: 4 is a magic number i pulled out of nooooowhere
120 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
121 foundport = true;
122 if (holdingWire == 1) {
123 if (i->second->source) {
124 eve = 114;
125 } else {
126 wireOriginAgent->join(wireOriginID, parent, i->first);
127 holdingWire = 0;
128 eve = 111;
130 } else if (holdingWire == 0) {
131 if (i->second->source) {
132 eve = 112;
133 holdingWire = 1;
134 wireOriginAgent = i->second->source;
135 wireOriginID = i->second->sourceid;
136 i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
137 i->second->source.clear();
138 } else {
139 eve = 110;
140 holdingWire = 2;
141 wireOriginAgent = parent;
142 wireOriginID = i->first;
145 break;
151 if (!foundport) {
152 if (holdingWire) {
153 holdingWire = 0;
154 eve = 113;
155 } else {
156 // if the agent isn't paused, tell it to handle a click
157 int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
158 if (scriptid != -1) {
159 // fire the script
160 // _p1_ is id of part for button clicks, according to Edynn code
161 // TODO: should _p1_ always be set? :)
162 if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);
164 // annoyingly queueScript doesn't reliably tell us if it did anything useful.
165 // TODO: work out the mess which is queueScript's return values etc
166 if (!parent->findScript(scriptid)) return;
168 // fire the associated pointer script too, if necessary
169 // TODO: fuzzie has no idea if this code is remotely correct
170 if (engine.version < 3) {
171 eve = 50;
172 } else {
173 eve = 101; // Pointer Activate 1
175 switch (scriptid) {
176 case 0: eve += 2; break; // deactivate
177 case 1: break; // activate 1
178 case 2: eve += 1; break; // activate 2
179 default: return;
185 if (eve != -1) firePointerScript(eve, a->getParent());
186 } else if (engine.version > 2) {
187 if (holdingWire) {
188 holdingWire = 0;
189 queueScript(113, 0);
190 } else {
191 queueScript(116, 0); // Pointer Clicked Background
194 } else if (event.button == buttonright) {
195 if (world.paused) return; // TODO: wrong?
197 // picking up and dropping are implictly handled by the scripts (well,
198 // messages) 4 and 5 TODO: check if this is correct behaviour, one issue
199 // is that this isn't instant, another is the messages might only be
200 // fired in c2e when you use MESG WRIT, in which case we'll need to
201 // manually set carrying to NULL and a here, respectively - fuzzie
202 if (carrying) {
203 // TODO: c1 support - these attributes are invalid for c1
204 if (!carrying->suffercollisions() || (carrying->validInRoomSystem() || engine.version == 1)) {
205 carrying->queueScript(5, this); // drop
207 int eve; if (engine.version < 3) eve = 54; else eve = 105;
208 firePointerScript(eve, carrying); // Pointer Drop
210 // TODO: is this the correct check?
211 if (carrying->sufferphysics() && carrying->suffercollisions()) {
212 // TODO: do this in the pointer agent?
213 carrying->velx.setFloat(velx.getFloat());
214 carrying->vely.setFloat(vely.getFloat());
216 } else {
217 // TODO: some kind of "fail to drop" animation/sound?
219 } else {
220 Agent *a = world.agentAt(x, y, false, true);
221 if (a) {
222 a->queueScript(4, this); // pickup
224 int eve; if (engine.version < 3) eve = 53; else eve = 104;
225 firePointerScript(eve, a); // Pointer Pickup
228 } else if (event.button == buttonmiddle) {
229 std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(x, y);
230 if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
231 Agent *a = world.agentAt(x, y, true);
232 if (a)
233 std::cout << "Agent under mouse is " << a->identify();
234 else
235 std::cout << "No agent under cursor";
236 std::cout << std::endl;
241 /* vim: set noet: */