1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 //-----------------------------------------------------------------------------
23 #include "T3D/aiConnection.h"
24 #include "console/engineAPI.h"
26 IMPLEMENT_CONOBJECT( AIConnection
);
28 ConsoleDocClass( AIConnection
,
29 "@brief Special client connection driven by an AI, rather than a human.\n\n"
31 "Unlike other net connections, AIConnection is intended to run unmanned. Rather than "
32 "gathering input from a human using a device, move events, triggers, and look events "
33 "are driven through functions like AIConnection::setMove.\n\n"
35 "In addition to having its own set of functions for managing client move events, "
36 "a member variable inherited by GameConnection is toggle: mAIControlled. This is useful "
37 "for a server to determine if a connection is AI driven via the function GameConnection::isAIControlled\n\n"
39 "AIConnection is an alternative to manually creating an AI driven game object. When you "
40 "want the server to manage AI, you will create a specific one from script using a "
41 "class like AIPlayer. If you do not want the server managing the AI and wish to simulate "
42 "a complete client connection, you will use AIConnection\n\n."
44 "To get more specific, if you want a strong alternative to AIPlayer (and wish to make use "
45 "of the AIConnection structure), consider AIClient. AIClient inherits from AIConnection, "
46 "contains quite a bit of functionality you will find in AIPlayer, and has its own Player "
50 "// Create a new AI client connection\n"
51 "%botConnection = aiConnect(\"MasterBlaster\" @ %i, -1, 0.5, false, \"SDF\", 1.0);\n\n"
52 "// In another area of the code, you can locate this and any other AIConnections\n"
53 "// using the isAIControlled function\n"
54 "for(%i = 0; %i < ClientGroup.getCount(); %i++)\n"
56 " %client = ClientGroup.getObject(%i);\n"
57 " if(%client.isAIControlled())\n"
59 " // React to this AI controlled client\n"
64 "@note This is a legacy class, which you are discouraged from using as it will "
65 "most likely be deprecated in a future version. For now it has been left in for "
66 "backwards compatibility with TGE and the old RTS Kit. Use GameConnection "
67 "and AIPlayer instead.\n\n"
69 "@see GameConnection, NetConnection, AIClient\n\n"
72 "@ingroup Networking\n"
74 //-----------------------------------------------------------------------------
76 AIConnection::AIConnection() {
82 //-----------------------------------------------------------------------------
84 void AIConnection::clearMoves( U32
)
86 // Clear the pending move list. This connection generates moves
87 // on the fly, so there are never any pending moves.
90 void AIConnection::setMove(Move
* m
)
95 const Move
& AIConnection::getMove()
100 /// Retrive the pending moves
102 * The GameConnection base class queues moves for delivery to the
103 * controll object. This function is normally used to retrieve the
104 * queued moves recieved from the client. The AI connection does not
105 * have a connected client and simply generates moves on-the-fly
106 * base on it's current state.
108 U32
AIConnection::getMoveList( Move
**lngMove
, U32
*numMoves
)
116 //-----------------------------------------------------------------------------
117 // Console functions & methods
118 //-----------------------------------------------------------------------------
120 //-----------------------------------------------------------------------------
122 static inline F32
moveClamp(F32 v
)
124 // Support function to convert/clamp the input into a move rotation
125 // which only allows 0 -> M_2PI.
126 F32 a
= mClampF(v
, -M_2PI_F
, M_2PI_F
);
127 return (a
< 0) ? a
+ M_2PI_F
: a
;
131 //-----------------------------------------------------------------------------
132 /// Construct and connect an AI connection object
133 ConsoleFunction(aiConnect
, S32
, 2, 20, "(...)"
134 "@brief Creates a new AIConnection, and passes arguments to its onConnect script callback.\n\n"
135 "@returns The newly created AIConnection\n"
136 "@see GameConnection for parameter information\n"
139 // Create the connection
140 AIConnection
*aiConnection
= new AIConnection();
141 aiConnection
->registerObject();
143 // Add the connection to the client group
144 SimGroup
*g
= Sim::getClientGroup();
145 g
->addObject( aiConnection
);
147 // Prep the arguments for the console exec...
148 // Make sure and leav args[1] empty.
149 const char* args
[21];
150 args
[0] = "onConnect";
151 args
[1] = NULL
; // Filled in later
152 for (S32 i
= 1; i
< argc
; i
++)
153 args
[i
+ 1] = argv
[i
];
155 // Execute the connect console function, this is the same
156 // onConnect function invoked for normal client connections
157 Con::execute(aiConnection
, argc
+ 1, args
);
158 return aiConnection
->getId();
162 //-----------------------------------------------------------------------------
163 DefineConsoleMethod(AIConnection
, setMove
, void, (const char * field
, F32 value
), ,"(string field, float value)"
164 "Set a field on the current move.\n\n"
165 "@param field One of {'x','y','z','yaw','pitch','roll'}\n"
166 "@param value Value to set field to.")
168 Move move
= object
->getMove();
170 // Ok, a little slow for now, but this is just an example..
171 if (!dStricmp(field
,"x"))
172 move
.x
= mClampF(value
,-1,1);
174 if (!dStricmp(field
,"y"))
175 move
.y
= mClampF(value
,-1,1);
177 if (!dStricmp(field
,"z"))
178 move
.z
= mClampF(value
,-1,1);
180 if (!dStricmp(field
,"yaw"))
181 move
.yaw
= moveClamp(value
);
183 if (!dStricmp(field
,"pitch"))
184 move
.pitch
= moveClamp(value
);
186 if (!dStricmp(field
,"roll"))
187 move
.roll
= moveClamp(value
);
190 object
->setMove(&move
);
193 DefineConsoleMethod(AIConnection
,getMove
,F32
, (const char * field
), ,"(string field)"
194 "Get the given field of a move.\n\n"
195 "@param field One of {'x','y','z','yaw','pitch','roll'}\n"
196 "@returns The requested field on the current move.")
198 const Move
& move
= object
->getMove();
199 if (!dStricmp(field
,"x"))
201 if (!dStricmp(field
,"y"))
203 if (!dStricmp(field
,"z"))
205 if (!dStricmp(field
,"yaw"))
207 if (!dStricmp(field
,"pitch"))
209 if (!dStricmp(field
,"roll"))
215 DefineConsoleMethod(AIConnection
,setFreeLook
,void,(bool isFreeLook
), ,"(bool isFreeLook)"
216 "Enable/disable freelook on the current move.")
218 Move move
= object
->getMove();
219 move
.freeLook
= isFreeLook
;
220 object
->setMove(&move
);
223 DefineConsoleMethod(AIConnection
, getFreeLook
, bool, (), ,"getFreeLook()"
224 "Is freelook on for the current move?")
226 return object
->getMove().freeLook
;
230 //-----------------------------------------------------------------------------
232 DefineConsoleMethod(AIConnection
,setTrigger
,void, (S32 idx
, bool set
), ,"(int trigger, bool set)"
235 if (idx
>= 0 && idx
< MaxTriggerKeys
)
237 Move move
= object
->getMove();
238 move
.trigger
[idx
] = set
;
239 object
->setMove(&move
);
243 DefineConsoleMethod(AIConnection
,getTrigger
,bool, (S32 idx
), ,"(int trigger)"
244 "Is the given trigger set?")
246 if (idx
>= 0 && idx
< MaxTriggerKeys
)
247 return object
->getMove().trigger
[idx
];
252 //-----------------------------------------------------------------------------
254 DefineConsoleMethod(AIConnection
,getAddress
,const char*,(), ,"")
256 // Override the netConnection method to return to indicate
257 // this is an ai connection.