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"
28 // TODO: change imagecount?
29 PointerAgent::PointerAgent(std::string spritefile
) : SimpleAgent(2, 1, 1, INT_MAX
, spritefile
, 0, 0) {
34 // TODO: verify attributes on the pointer in c2e
35 attr
.setInt(256); // camera shy
38 void PointerAgent::finishInit() {
41 // float relative to main camera
42 attr
.setInt(attr
.getInt() & 32);
46 void PointerAgent::carry(AgentRef a
) {
49 int eve
; if (engine
.version
< 3) eve
= 53; else eve
= 104;
50 firePointerScript(eve
, a
); // Pointer Pickup
53 void PointerAgent::drop(AgentRef a
) {
56 int eve
; if (engine
.version
< 3) eve
= 54; else eve
= 105;
57 firePointerScript(eve
, a
); // Pointer Drop
60 // TODO: this should have a queueScript equiv too
61 void PointerAgent::firePointerScript(unsigned short event
, Agent
*src
) {
62 assert(src
); // TODO: I /think/ this should only be called by the engine..
63 shared_ptr
<script
> s
= src
->findScript(event
);
64 if (!s
&& engine
.version
< 3) { // TODO: are we sure this doesn't apply to c2e?
65 s
= findScript(event
); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
68 if (!vm
) vm
= world
.getVM(this);
69 if (vm
->fireScript(s
, false, src
)) { // TODO: should FROM be src?
75 void PointerAgent::physicsTick() {
76 // TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
79 void PointerAgent::kill() {
80 // pointer agent isn't killable
83 void PointerAgent::setHotspot(int x
, int y
) {
88 void PointerAgent::handleEvent(SomeEvent
&event
) {
89 int x
= pointerX(), y
= pointerY();
91 if (event
.type
== eventmousemove
) {
92 moveTo(event
.x
+ world
.camera
.getX() - hotspotx
, event
.y
+ world
.camera
.getY() - hotspoty
);
93 velx
.setInt(event
.xrel
* 4);
94 vely
.setInt(event
.yrel
* 4);
97 editAgent
->moveTo(pointerX(), pointerY());
99 // middle mouse button scrolling
100 if (event
.button
& buttonmiddle
)
101 world
.camera
.moveTo(world
.camera
.getX() - event
.xrel
, world
.camera
.getY() - event
.yrel
, jump
);
102 } else if (!handle_events
) {
103 /* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
105 } else if (event
.type
== eventmousebuttondown
) {
106 // do our custom handling
107 if (event
.button
== buttonleft
) {
108 CompoundPart
*a
= world
.partAt(x
, y
);
109 if (a
/* && a->canActivate() */) { // TODO
110 Agent
* parent
= a
->getParent();
114 bool foundport
= false;
115 if (engine
.version
> 2) {
116 for (std::map
<unsigned int, boost::shared_ptr
<OutputPort
> >::iterator i
= parent
->outports
.begin();
117 i
!= parent
->outports
.end(); i
++) {
118 // TODO: 4 is a magic number i pulled out of nooooowhere
119 if (abs(i
->second
->x
+ parent
->x
- x
) < 4 && abs(i
->second
->y
+ parent
->y
- y
) < 4) {
121 if (holdingWire
== 2) {
122 parent
->join(i
->first
, wireOriginAgent
, wireOriginID
);
125 } else if (holdingWire
== 0) {
128 wireOriginAgent
= parent
;
129 wireOriginID
= i
->first
;
135 for (std::map
<unsigned int, boost::shared_ptr
<InputPort
> >::iterator i
= parent
->inports
.begin();
136 i
!= parent
->inports
.end(); i
++) {
137 // TODO: 4 is a magic number i pulled out of nooooowhere
138 if (abs(i
->second
->x
+ parent
->x
- x
) < 4 && abs(i
->second
->y
+ parent
->y
- y
) < 4) {
140 if (holdingWire
== 1) {
141 if (i
->second
->source
) {
144 wireOriginAgent
->join(wireOriginID
, parent
, i
->first
);
148 } else if (holdingWire
== 0) {
149 if (i
->second
->source
) {
152 wireOriginAgent
= i
->second
->source
;
153 wireOriginID
= i
->second
->sourceid
;
154 i
->second
->source
->outports
[i
->second
->sourceid
]->dests
.remove(std::pair
<AgentRef
, unsigned int>(parent
, i
->first
));
155 i
->second
->source
.clear();
159 wireOriginAgent
= parent
;
160 wireOriginID
= i
->first
;
174 // if the agent isn't paused, tell it to handle a click
175 int scriptid
= a
->handleClick(x
- a
->x
- parent
->x
, y
- a
->y
- parent
->y
);
176 if (scriptid
!= -1) {
178 // _p1_ is id of part for button clicks, according to Edynn code
179 // TODO: should _p1_ always be set? :)
180 if (!parent
->paused
) parent
->queueScript(scriptid
, world
.hand(), (int)a
->id
);
182 // annoyingly queueScript doesn't reliably tell us if it did anything useful.
183 // TODO: work out the mess which is queueScript's return values etc
184 if (!parent
->findScript(scriptid
)) return;
186 // fire the associated pointer script too, if necessary
187 // TODO: fuzzie has no idea if this code is remotely correct
188 if (engine
.version
< 3) {
191 eve
= 101; // Pointer Activate 1
194 case 0: eve
+= 2; break; // deactivate
195 case 1: break; // activate 1
196 case 2: eve
+= 1; break; // activate 2
203 if (eve
!= -1) firePointerScript(eve
, a
->getParent());
204 } else if (engine
.version
> 2) {
209 queueScript(116, 0); // Pointer Clicked Background
212 } else if (event
.button
== buttonright
) {
218 if (world
.paused
) return; // TODO: wrong?
220 // picking up and dropping are implictly handled by the scripts (well,
221 // messages) 4 and 5 TODO: check if this is correct behaviour, one issue
222 // is that this isn't instant, another is the messages might only be
223 // fired in c2e when you use MESG WRIT, in which case we'll need to
224 // manually set carrying to NULL and a here, respectively - fuzzie
226 if (engine
.version
== 1) {
227 // ensure there's a room to drop into, in C1
228 MetaRoom
* m
= world
.map
.metaRoomAt(x
, y
);
230 shared_ptr
<Room
> r
= m
->nextFloorFromPoint(x
, y
);
233 carrying
->queueScript(5, this); // drop
236 } else if (!carrying
->suffercollisions() || carrying
->validInRoomSystem()) {
237 carrying
->queueScript(5, this); // drop
239 // TODO: is this the correct check?
240 if (carrying
->sufferphysics() && carrying
->suffercollisions()) {
241 // TODO: do this in the pointer agent?
242 carrying
->velx
.setFloat(velx
.getFloat());
243 carrying
->vely
.setFloat(vely
.getFloat());
249 // TODO: some kind of "fail to drop" animation/sound?
251 Agent
*a
= world
.agentAt(x
, y
, false, true);
253 a
->queueScript(4, this); // pickup
256 } else if (event
.button
== buttonmiddle
) {
257 std::vector
<shared_ptr
<Room
> > rooms
= world
.map
.roomsAt(x
, y
);
258 if (rooms
.size() > 0) std::cout
<< "Room at cursor is " << rooms
[0]->id
<< std::endl
;
259 Agent
*a
= world
.agentAt(x
, y
, true);
261 std::cout
<< "Agent under mouse is " << a
->identify();
263 std::cout
<< "No agent under cursor";
264 std::cout
<< std::endl
;