- Linux/GCC (as usual :P)
- Ported lockless code to gcc inline assembly - A few new net messages (gather, attack, add waypoint) - Support for new messages in network->entity order converter - Implemented rudimentary JS interface for Interaction - issueCommand JS API, connected to the network - Removed Interaction stuff now replaced by JS - And something in there should probably break VS builds :P This was SVN commit r2316.
This commit is contained in:
parent
600a55b7d7
commit
d0f7cb015c
@ -5,6 +5,7 @@
|
||||
#include "GameView.h"
|
||||
#include "Game.h"
|
||||
#include "Camera.h"
|
||||
#include "Interact.h"
|
||||
|
||||
#include "Matrix3D.h"
|
||||
#include "Renderer.h"
|
||||
@ -66,6 +67,8 @@ CGameView::CGameView(CGame *pGame):
|
||||
m_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
m_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
g_Renderer.SetCamera(m_Camera);
|
||||
|
||||
ONCE( ScriptingInit(); );
|
||||
}
|
||||
|
||||
CGameView::~CGameView()
|
||||
@ -73,6 +76,13 @@ CGameView::~CGameView()
|
||||
UnloadResources();
|
||||
}
|
||||
|
||||
void CGameView::ScriptingInit()
|
||||
{
|
||||
AddMethod<bool, &CGameView::JSI_StartCustomSelection>("startCustomSelection", 0);
|
||||
AddMethod<bool, &CGameView::JSI_EndCustomSelection>("endCustomSelection", 0);
|
||||
|
||||
CJSObject<CGameView>::ScriptingInit("GameView");
|
||||
}
|
||||
|
||||
int CGameView::Initialize(CGameAttributes *pAttribs)
|
||||
{
|
||||
@ -691,3 +701,15 @@ int game_view_handler(const SDL_Event* ev)
|
||||
|
||||
return EV_PASS;
|
||||
}
|
||||
|
||||
bool CGameView::JSI_StartCustomSelection(JSContext* context, unsigned int argc, jsval* argv)
|
||||
{
|
||||
StartCustomSelection();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameView::JSI_EndCustomSelection(JSContext* context, unsigned int argc, jsval* argv)
|
||||
{
|
||||
ResetInteraction();
|
||||
return true;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "Camera.h"
|
||||
#include "Vector3D.h"
|
||||
|
||||
#include "scripting/ScriptableObject.h"
|
||||
|
||||
class CGame;
|
||||
class CGameAttributes;
|
||||
class CWorld;
|
||||
@ -12,7 +14,7 @@ class CUnitManager;
|
||||
class CProjectileManager;
|
||||
class CModel;
|
||||
|
||||
class CGameView
|
||||
class CGameView: public CJSObject<CGameView>
|
||||
{
|
||||
CGame *m_pGame;
|
||||
CWorld *m_pWorld;
|
||||
@ -57,6 +59,12 @@ class CGameView
|
||||
// UnloadResources(): Unload all graphics resources loaded by InitResources
|
||||
void UnloadResources();
|
||||
|
||||
// JS Interface
|
||||
bool JSI_StartCustomSelection(JSContext *cx, uintN argc, jsval *argv);
|
||||
bool JSI_EndCustomSelection(JSContext *cx, uintN argc, jsval *argv);
|
||||
|
||||
static void ScriptingInit();
|
||||
|
||||
public:
|
||||
CGameView(CGame *pGame);
|
||||
~CGameView();
|
||||
|
@ -308,7 +308,7 @@ bool CObjectBase::Load(const char* filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "Invalid actor format (unrecognised root element '%s')", XeroFile.getElementString(root.getNodeName()));
|
||||
LOG(ERROR, LOG_CATEGORY, "Invalid actor format (unrecognised root element '%s')", XeroFile.getElementString(root.getNodeName()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ class CModel;
|
||||
class CSkeletonAnim;
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "CStr.h"
|
||||
|
||||
class CObjectBase
|
||||
|
@ -17,8 +17,9 @@
|
||||
|
||||
#include "lib/res/vfs.h"
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
#include <sstream>
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
CObjectEntry::CObjectEntry(int type, CObjectBase* base)
|
||||
: m_Model(0), m_Type(type), m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
|
@ -101,7 +101,8 @@ CObjectEntry* CObjectManager::FindObject(const char* objname)
|
||||
CObjectBase::variation_key var;
|
||||
base->CalculateVariation(choices, var);
|
||||
|
||||
return FindObjectVariation(base, var, var.begin());
|
||||
CObjectBase::variation_key::iterator vars_it=var.begin();
|
||||
return FindObjectVariation(base, var, vars_it);
|
||||
}
|
||||
|
||||
CObjectEntry* CObjectManager::FindObjectVariation(const char* objname, CObjectBase::variation_key vars, CObjectBase::variation_key::iterator& vars_it)
|
||||
|
@ -31,7 +31,7 @@ class CObjectManager : public Singleton<CObjectManager>
|
||||
public:
|
||||
struct ObjectKey
|
||||
{
|
||||
ObjectKey(CStr& name, CObjectBase::variation_key& var)
|
||||
ObjectKey(const CStr& name, const CObjectBase::variation_key& var)
|
||||
: ActorName(name), ActorVariation(var) {}
|
||||
|
||||
CStr ActorName;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#ifndef CGUIList_H
|
||||
#define CGUIList_H
|
||||
|
||||
#include "GUIText.h"
|
||||
#include "GUItext.h"
|
||||
|
||||
class CGUIList
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ void CList::SetupText()
|
||||
AddText(text);
|
||||
}
|
||||
|
||||
m_ItemsYPositions[i] = buffered_y;
|
||||
m_ItemsYPositions[pList->m_Items.size()] = buffered_y;
|
||||
|
||||
//if (! scrollbar)
|
||||
// CalculateTextPosition(m_CachedActualSize, m_TextPos, *m_GeneratedTexts[0]);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "lib.h"
|
||||
@ -30,7 +31,6 @@
|
||||
#define PERFORM_SELF_TEST 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
liberties taken:
|
||||
- R(H) will remain constant
|
||||
|
@ -55,6 +55,13 @@ need only be renamed (e.g. _open, _stat).
|
||||
|
||||
#else
|
||||
|
||||
// unix/linux/glibc/gcc says that this macro has to be defined when including
|
||||
// stdint.h from C++ for stdint.h to define SIZE_MAX and friends
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
|
@ -10,5 +10,10 @@
|
||||
#ifdef _WIN32
|
||||
# include "sysdep/win/wposix_types.h"
|
||||
#else
|
||||
// unix/linux/glibc/gcc says that this macro has to be defined when including
|
||||
// stdint.h from C++ for stdint.h to define SIZE_MAX and friends
|
||||
# ifndef __STDC_LIMIT_MACROS
|
||||
# define __STDC_LIMIT_MACROS
|
||||
# endif
|
||||
# include <stdint.h>
|
||||
#endif // #ifdef _WIN32
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "detect.h"
|
||||
#include "adts.h"
|
||||
#include "sysdep/sysdep.h"
|
||||
#include "byte_order.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
@ -32,11 +32,11 @@
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
// currently not thread safe. will have to change that if
|
||||
// a prefetch thread is to be used.
|
||||
// not safe to call before main!
|
||||
@ -294,7 +294,7 @@ struct DirAndPath
|
||||
: dir(d), path(p) {}
|
||||
};
|
||||
|
||||
typedef std::deque<const DirAndPath> DirQueue;
|
||||
typedef std::deque<DirAndPath> DirQueue;
|
||||
|
||||
|
||||
// passed through TDir::addR's file_enum to dirent_cb
|
||||
|
@ -119,7 +119,7 @@ bool path_component_valid(const char* name)
|
||||
|
||||
|
||||
// convenience function
|
||||
inline void path_copy(char* dst, const char* src)
|
||||
void path_copy(char* dst, const char* src)
|
||||
{
|
||||
strcpy_s(dst, VFS_MAX_PATH, src);
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
{
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef T T;
|
||||
typedef ::T T;
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const T* pointer;
|
||||
@ -623,14 +623,14 @@ void tree_init()
|
||||
tree_root_dir->init();
|
||||
}
|
||||
|
||||
inline void tree_clear()
|
||||
void tree_clear()
|
||||
{
|
||||
tree_root_dir->clearR();
|
||||
}
|
||||
|
||||
|
||||
// write a representation of the VFS tree to stdout.
|
||||
inline void tree_display()
|
||||
void tree_display()
|
||||
{
|
||||
tree_root_dir->displayR(0);
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef SYSDEP_CPU_H
|
||||
#define SYSDEP_CPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -40,3 +43,5 @@ extern void serialize();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#ifdef _M_IX86
|
||||
|
||||
#include "lib.h"
|
||||
#include "posix.h"
|
||||
#include "ia32.h"
|
||||
@ -37,6 +35,7 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// replace pathetic MS libc implementation
|
||||
#ifdef _WIN32
|
||||
@ -616,4 +615,49 @@ void serialize()
|
||||
__asm cpuid
|
||||
}
|
||||
|
||||
#endif // #ifndef _M_IX86
|
||||
#else // #ifndef __GNUC__
|
||||
|
||||
bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value)
|
||||
{
|
||||
uintptr_t prev;
|
||||
|
||||
assert2(location >= (uintptr_t *)0x10000);
|
||||
|
||||
__asm__ __volatile__("lock; cmpxchgl %1,%2"
|
||||
: "=a"(prev) // %0: Result in eax should be stored in prev
|
||||
: "q"(new_value), // %1: new_value -> e[abcd]x
|
||||
"m"(*location), // %2: Memory operand
|
||||
"0"(expected) // Stored in same place as %0
|
||||
: "memory"); // We make changes in memory
|
||||
return prev==expected;
|
||||
}
|
||||
|
||||
void atomic_add(intptr_t *location, intptr_t increment)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"cmpb $1, %1;"
|
||||
"je 1f;"
|
||||
"lock;"
|
||||
"1: addl %3, %0"
|
||||
: "=m" (*location) /* %0: Output into *location */
|
||||
: "m" (cpus), /* %1: Input for cpu check */
|
||||
"m" (*location), /* %2: *location is also an input */
|
||||
"r" (increment) /* %3: Increment (store in register) */
|
||||
: "memory"); /* clobbers memory (*location) */
|
||||
}
|
||||
|
||||
void mfence()
|
||||
{
|
||||
// no cpu caps stored in gcc compiles, so we can't check for SSE2 support
|
||||
/*
|
||||
if (ia32_cap(SSE2))
|
||||
__asm__ __volatile__ ("mfence");
|
||||
*/
|
||||
}
|
||||
|
||||
void serialize()
|
||||
{
|
||||
__asm__ __volatile__ ("cpuid");
|
||||
}
|
||||
|
||||
#endif // #ifdef __GNUC__
|
||||
|
@ -18,8 +18,8 @@
|
||||
#ifndef IA32_H
|
||||
#define IA32_H
|
||||
|
||||
#ifndef _M_IX86
|
||||
#error "including ia32.h without _M_IX86 defined"
|
||||
#if !(defined(__GNUC__) && defined(i386)) && !defined(_M_IX86)
|
||||
#error "including ia32.h without _M_IX86 (or both __GNUC__ and i386) defined"
|
||||
#endif
|
||||
|
||||
#include "lib/types.h"
|
||||
|
@ -13,13 +13,18 @@ static bool initialized=false;
|
||||
|
||||
static std::map<intptr_t, std::string> dirs;
|
||||
|
||||
void fam_deinit()
|
||||
{
|
||||
FAMClose(&fc);
|
||||
}
|
||||
|
||||
int dir_add_watch(const char* const n_full_path, intptr_t* const watch)
|
||||
{
|
||||
if(!initialized)
|
||||
{
|
||||
CHECK_ERR(FAMOpen2(&fc, "lib_res"));
|
||||
atexit2((void*)FAMClose, (uintptr_t)&fc);
|
||||
initialized = true;
|
||||
atexit(fam_deinit);
|
||||
}
|
||||
|
||||
FAMRequest req;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "timer.h"
|
||||
#include "sysdep/sysdep.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <Xatom.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "sysdep/debug.h"
|
||||
#include "detect.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -152,7 +153,7 @@ wchar_t *clipboard_get()
|
||||
&len, &bytes_left,
|
||||
&data);
|
||||
if (result != Success)
|
||||
debug_out("clipboard_get: result: %d type:%d len:%d format:%d bytes_left:%d\n",
|
||||
debug_printf("clipboard_get: result: %d type:%d len:%d format:%d bytes_left:%d\n",
|
||||
result, (int)type, len, format, bytes_left);
|
||||
if (result == Success && bytes_left > 0)
|
||||
{
|
||||
@ -163,8 +164,8 @@ wchar_t *clipboard_get()
|
||||
|
||||
if (result == Success)
|
||||
{
|
||||
debug_out("clipboard_get: XGetWindowProperty succeeded, returning data\n");
|
||||
debug_out("clipboard_get: data was: \"%s\", type was %d, XA_STRING atom is %d\n", data, type, XA_STRING);
|
||||
debug_printf("clipboard_get: XGetWindowProperty succeeded, returning data\n");
|
||||
debug_printf("clipboard_get: data was: \"%s\", type was %d, XA_STRING atom is %d\n", data, type, XA_STRING);
|
||||
|
||||
if (type == XA_STRING) //Latin-1: Just copy into low byte of wchar_t
|
||||
{
|
||||
@ -177,7 +178,7 @@ wchar_t *clipboard_get()
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_out("clipboard_get: XGetWindowProperty failed!\n");
|
||||
debug_printf("clipboard_get: XGetWindowProperty failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -807,6 +807,8 @@ TIMER(InitScripting)
|
||||
g_ScriptingHost.DefineConstant( "ORDER_ATTACK", CEntityOrder::ORDER_ATTACK_MELEE );
|
||||
g_ScriptingHost.DefineConstant( "ORDER_GATHER", CEntityOrder::ORDER_GATHER );
|
||||
|
||||
CNetMessage::ScriptingInit();
|
||||
|
||||
JSI_Camera::init();
|
||||
JSI_Console::init();
|
||||
|
||||
|
@ -134,9 +134,9 @@ namespace ConfigNamespace_JS
|
||||
}
|
||||
|
||||
JSFunctionSpec Funcs[] = {
|
||||
{ "WriteFile", WriteFile, 2, 0, 0},
|
||||
{ "Reload", Reload, 0, 0, 0},
|
||||
{ "SetFile", SetFile, 1, 0, 0},
|
||||
{ "writeFile", WriteFile, 2, 0, 0},
|
||||
{ "reload", Reload, 0, 0, 0},
|
||||
{ "setFile", SetFile, 1, 0, 0},
|
||||
{0}
|
||||
};
|
||||
};
|
||||
|
@ -11,177 +11,6 @@
|
||||
|
||||
CGame *g_Game=NULL;
|
||||
|
||||
/*
|
||||
<<<<<<< .mine
|
||||
namespace PlayerArray_JS
|
||||
{
|
||||
JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
CGameAttributes *pInstance=(CGameAttributes *)JS_GetPrivate(cx, obj);
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_FALSE;
|
||||
uint index=g_ScriptingHost.ValueToInt(id);
|
||||
|
||||
// Clamp to a preset upper bound.
|
||||
// FIXME I guess we'll ultimately have max players as a config variable
|
||||
if (pInstance->m_NumPlayers > PS_MAX_PLAYERS)
|
||||
pInstance->m_NumPlayers = PS_MAX_PLAYERS;
|
||||
|
||||
// Resize array according to new number of players (note that the array
|
||||
// size will go up to PS_MAX_PLAYERS, but will never be made smaller -
|
||||
// this to avoid losing player pointers and make sure they are all
|
||||
// reclaimed in the end - it's just simpler that way ;-) )
|
||||
if (pInstance->m_NumPlayers+1 > pInstance->m_Players.size())
|
||||
{
|
||||
for (size_t i=pInstance->m_Players.size();i<=index;i++)
|
||||
{
|
||||
CPlayer *pNewPlayer=new CPlayer((uint)i);
|
||||
pNewPlayer->SetUpdateCallback(pInstance->m_PlayerUpdateCB, pInstance->m_PlayerUpdateCBData);
|
||||
pInstance->m_Players.push_back(pNewPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (index > pInstance->m_NumPlayers)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp=OBJECT_TO_JSVAL(pInstance->m_Players[index]->GetScript());
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool SetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSClass Class = {
|
||||
"PlayerArray", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
GetProperty, SetProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
JSBool Construct( JSContext* cx, JSObject* obj, uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
if (argc != 0)
|
||||
return JS_FALSE;
|
||||
|
||||
JSObject *newObj=JS_NewObject(cx, &Class, NULL, obj);
|
||||
*rval=OBJECT_TO_JSVAL(newObj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
CGameAttributes::CGameAttributes():
|
||||
m_UpdateCB(NULL),
|
||||
m_MapFile("test01.pmp"),
|
||||
m_NumPlayers(2)
|
||||
{
|
||||
ONCE(
|
||||
g_ScriptingHost.DefineCustomObjectType(&PlayerArray_JS::Class,
|
||||
PlayerArray_JS::Construct, 0, NULL, NULL, NULL, NULL);
|
||||
|
||||
ScriptingInit();
|
||||
);
|
||||
|
||||
m_PlayerArrayJS=g_ScriptingHost.CreateCustomObject("PlayerArray");
|
||||
JS_SetPrivate(g_ScriptingHost.GetContext(), m_PlayerArrayJS, this);
|
||||
|
||||
AddSynchedProperty(L"mapFile", &m_MapFile);
|
||||
AddSynchedProperty(L"numPlayers", &m_NumPlayers);
|
||||
|
||||
m_Players.resize(4);
|
||||
for (int i=0;i<4;i++)
|
||||
m_Players[i]=new CPlayer(i);
|
||||
|
||||
m_Players[0]->SetName(L"Gaia");
|
||||
m_Players[0]->SetColour(SPlayerColour(0.2f, 0.7f, 0.2f));
|
||||
|
||||
m_Players[1]->SetName(L"Acumen");
|
||||
m_Players[1]->SetColour(SPlayerColour(1.0f, 0.0f, 0.0f));
|
||||
|
||||
m_Players[2]->SetName(L"Boco the Insignificant");
|
||||
m_Players[2]->SetColour(SPlayerColour(0.0f, 0.0f, 1.0f));
|
||||
|
||||
m_Players[3]->SetName(L"NoMonkey");
|
||||
m_Players[3]->SetColour(SPlayerColour(0.5f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
CGameAttributes::~CGameAttributes()
|
||||
{
|
||||
std::vector<CPlayer *>::iterator it=m_Players.begin();
|
||||
while (it != m_Players.end())
|
||||
{
|
||||
delete *it;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
jsval CGameAttributes::JSGetPlayers()
|
||||
{
|
||||
return OBJECT_TO_JSVAL(m_PlayerArrayJS);
|
||||
}
|
||||
|
||||
void CGameAttributes::SetValue(CStrW name, CStrW value)
|
||||
{
|
||||
ISynchedJSProperty *prop=GetSynchedProperty(name);
|
||||
if (prop)
|
||||
{
|
||||
prop->FromString(value);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameAttributes::Update(CStrW name, ISynchedJSProperty *attrib)
|
||||
{
|
||||
if (m_UpdateCB)
|
||||
m_UpdateCB(name, attrib->ToString(), m_UpdateCBData);
|
||||
}
|
||||
|
||||
void CGameAttributes::SetPlayerUpdateCallback(CPlayer::UpdateCallback *cb, void *userdata)
|
||||
{
|
||||
m_PlayerUpdateCB=cb;
|
||||
m_PlayerUpdateCBData=userdata;
|
||||
|
||||
for (size_t i=0;i<m_Players.size();i++)
|
||||
{
|
||||
m_Players[i]->SetUpdateCallback(cb, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameAttributes::ScriptingInit()
|
||||
{
|
||||
AddClassProperty(L"players", (GetFn)&CGameAttributes::JSGetPlayers);
|
||||
CJSObject<CGameAttributes>::ScriptingInit( "Game" );
|
||||
|
||||
}
|
||||
|
||||
/*void CGameAttributes::CreateJSObject()
|
||||
{
|
||||
CAttributeMap::CreateJSObject();
|
||||
|
||||
ONCE(
|
||||
g_ScriptingHost.DefineCustomObjectType(&PlayerArray_JS::Class,
|
||||
PlayerArray_JS::Construct, 0, NULL, NULL, NULL, NULL);
|
||||
);
|
||||
|
||||
m_PlayerArrayJS=g_ScriptingHost.CreateCustomObject("PlayerArray");
|
||||
JS_SetPrivate(g_ScriptingHost.GetContext(), m_PlayerArrayJS, this);
|
||||
int flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT;
|
||||
JS_DefineProperty(g_ScriptingHost.GetContext(), m_JSObject, "players",
|
||||
OBJECT_TO_JSVAL(m_PlayerArrayJS), NULL, NULL, flags);
|
||||
}
|
||||
|
||||
JSBool CGameAttributes::GetJSProperty(jsval id, jsval *ret)
|
||||
{
|
||||
CStr name=g_ScriptingHost.ValueToString(id);
|
||||
if (name == CStr("players"))
|
||||
return JS_TRUE;
|
||||
return CAttributeMap::GetJSProperty(id, ret);
|
||||
}*//*
|
||||
|
||||
=======
|
||||
>>>>>>> .r2037
|
||||
*/
|
||||
// Disable "warning C4355: 'this' : used in base member initializer list".
|
||||
// "The base-class constructors and class member constructors are called before
|
||||
// this constructor. In effect, you've passed a pointer to an unconstructed
|
||||
|
@ -18,59 +18,6 @@ ERROR_GROUP(Game);
|
||||
// This may be overriden by system.cfg ("max_players")
|
||||
#define PS_MAX_PLAYERS 6
|
||||
|
||||
/*
|
||||
<<<<<<< .mine
|
||||
namespace PlayerArray_JS
|
||||
{
|
||||
JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
};
|
||||
|
||||
#define g_GameAttributes CGameAttributes::GetSingleton()
|
||||
class CGameAttributes:
|
||||
public CSynchedJSObject<CGameAttributes>,
|
||||
public Singleton<CGameAttributes>
|
||||
{
|
||||
public:
|
||||
typedef void (UpdateCallback)(CStrW name, CStrW newValue, void *data);
|
||||
|
||||
private:
|
||||
friend JSBool PlayerArray_JS::GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
|
||||
virtual void Update(CStrW name, ISynchedJSProperty *attrib);
|
||||
|
||||
UpdateCallback *m_UpdateCB;
|
||||
void *m_UpdateCBData;
|
||||
|
||||
CPlayer::UpdateCallback *m_PlayerUpdateCB;
|
||||
void *m_PlayerUpdateCBData;
|
||||
|
||||
jsval JSGetPlayers();
|
||||
|
||||
public:
|
||||
CStrW m_MapFile;
|
||||
uint m_NumPlayers;
|
||||
|
||||
CGameAttributes();
|
||||
virtual ~CGameAttributes();
|
||||
|
||||
void SetValue(CStrW name, CStrW value);
|
||||
|
||||
inline void SetUpdateCallback(UpdateCallback *cb, void *userdata)
|
||||
{
|
||||
m_UpdateCB=cb;
|
||||
m_UpdateCBData=userdata;
|
||||
}
|
||||
|
||||
void SetPlayerUpdateCallback(CPlayer::UpdateCallback *cb, void *userdata);
|
||||
|
||||
std::vector <CPlayer *> m_Players;
|
||||
JSObject *m_PlayerArrayJS;
|
||||
|
||||
static void ScriptingInit();
|
||||
};
|
||||
=======
|
||||
>>>>>>> .r2037
|
||||
*/
|
||||
class CGame
|
||||
{
|
||||
CWorld m_World;
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "CLogger.h"
|
||||
|
||||
#include "Interact.h"
|
||||
#include "Renderer.h"
|
||||
#include "input.h"
|
||||
@ -22,6 +25,8 @@ extern CStr g_CursorName;
|
||||
static const float SELECT_DBLCLICK_RATE = 0.5f;
|
||||
const int ORDER_DELAY = 5;
|
||||
|
||||
bool customSelectionMode=false;
|
||||
|
||||
void CSelectedEntities::addSelection( HEntity entity )
|
||||
{
|
||||
m_group = -1;
|
||||
@ -356,6 +361,10 @@ void CSelectedEntities::update()
|
||||
{
|
||||
static std::vector<HEntity> lastSelection;
|
||||
|
||||
// Drop out immediately if we're in some special interaction mode
|
||||
if (customSelectionMode)
|
||||
return;
|
||||
|
||||
if( !( m_selected == lastSelection ) )
|
||||
{
|
||||
g_JSGameEvents.FireSelectionChanged( m_selectionChanged );
|
||||
@ -367,17 +376,18 @@ void CSelectedEntities::update()
|
||||
// Can't order anything off the map
|
||||
if( !g_Game->GetWorld()->GetTerrain()->isOnMap( g_Mouseover.m_worldposition ) )
|
||||
{
|
||||
m_contextOrder = -1;
|
||||
m_defaultCommand = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Quick count to see which is the modal default order.
|
||||
|
||||
int defaultPoll[CEntityOrder::ORDER_LAST];
|
||||
std::map<CStrW, int, CStrW_hash_compare> defaultCursor[CEntityOrder::ORDER_LAST];
|
||||
const int numCommands=NMT_COMMAND_LAST - NMT_COMMAND_FIRST;
|
||||
int defaultPoll[numCommands];
|
||||
std::map<CStrW, int, CStrW_hash_compare> defaultCursor[numCommands];
|
||||
|
||||
int t, vote;
|
||||
for( t = 0; t < CEntityOrder::ORDER_LAST; t++ )
|
||||
for( t = 0; t < numCommands; t++ )
|
||||
defaultPoll[t] = 0;
|
||||
|
||||
std::vector<HEntity>::iterator it;
|
||||
@ -385,9 +395,9 @@ void CSelectedEntities::update()
|
||||
{
|
||||
CEventTargetChanged evt( g_Mouseover.m_target );
|
||||
(*it)->DispatchEvent( &evt );
|
||||
vote = evt.m_defaultAction;
|
||||
vote = evt.m_defaultAction - NMT_COMMAND_FIRST;
|
||||
|
||||
if( ( vote >= 0 ) && ( vote < CEntityOrder::ORDER_LAST ) )
|
||||
if( ( vote >= 0 ) && ( vote < numCommands ) )
|
||||
{
|
||||
defaultPoll[vote]++;
|
||||
defaultCursor[vote][evt.m_defaultCursor]++;
|
||||
@ -395,14 +405,14 @@ void CSelectedEntities::update()
|
||||
}
|
||||
|
||||
vote = -1;
|
||||
for( t = 0; t < CEntityOrder::ORDER_LAST; t++ )
|
||||
for( t = 0; t < numCommands; t++ )
|
||||
{
|
||||
if( ( vote == -1 ) || ( defaultPoll[t] > defaultPoll[vote] ) )
|
||||
vote = t;
|
||||
}
|
||||
|
||||
std::map<CStrW, int, CStrW_hash_compare>::iterator itv;
|
||||
m_contextOrder = vote;
|
||||
m_defaultCommand = vote + NMT_COMMAND_FIRST;
|
||||
|
||||
// Now find the most appropriate cursor
|
||||
t = 0;
|
||||
@ -422,176 +432,6 @@ void CSelectedEntities::update()
|
||||
|
||||
}
|
||||
|
||||
void CSelectedEntities::setContext( int contextOrder )
|
||||
{
|
||||
assert( isContextValid( contextOrder ) );
|
||||
m_contextOrder = contextOrder;
|
||||
}
|
||||
|
||||
bool CSelectedEntities::nextContext()
|
||||
{
|
||||
// No valid orders?
|
||||
if( m_contextOrder == -1 ) return( false );
|
||||
int t = m_contextOrder + 1;
|
||||
while( t != m_contextOrder )
|
||||
{
|
||||
if( t == CEntityOrder::ORDER_LAST ) t = 0;
|
||||
if( isContextValid( t ) ) break;
|
||||
t++;
|
||||
}
|
||||
if( m_contextOrder == t )
|
||||
return( false );
|
||||
m_contextOrder = t;
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool CSelectedEntities::previousContext()
|
||||
{
|
||||
// No valid orders?
|
||||
if( m_contextOrder == -1 ) return( false );
|
||||
int t = m_contextOrder - 1;
|
||||
while( t != m_contextOrder )
|
||||
{
|
||||
if( isContextValid( t ) ) break;
|
||||
if( t == 0 ) t = CEntityOrder::ORDER_LAST;
|
||||
t--;
|
||||
}
|
||||
if( m_contextOrder == t )
|
||||
return( false );
|
||||
m_contextOrder = t;
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool CSelectedEntities::isContextValid( int contextOrder )
|
||||
{
|
||||
if( contextOrder == -1 ) return( false );
|
||||
|
||||
// Can't order anything off the map
|
||||
if( !g_Game->GetWorld()->GetTerrain()->isOnMap( g_Mouseover.m_worldposition ) )
|
||||
return( false );
|
||||
|
||||
// Check to see if any member of the selection supports this order type.
|
||||
std::vector<HEntity>::iterator it;
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
if( (*it)->acceptsOrder( contextOrder, g_Mouseover.m_target ) )
|
||||
return( true );
|
||||
return( false );
|
||||
}
|
||||
|
||||
void CSelectedEntities::contextOrder( bool pushQueue )
|
||||
{
|
||||
CCamera *pCamera=g_Game->GetView()->GetCamera();
|
||||
CTerrain *pTerrain=g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
std::vector<HEntity>::iterator it;
|
||||
CEntityOrder context, contextRandomized;
|
||||
(int&)context.m_type = m_contextOrder;
|
||||
|
||||
switch( m_contextOrder )
|
||||
{
|
||||
// PATROL order: temporatily disabled until we define the network command for it
|
||||
case CEntityOrder::ORDER_PATROL:
|
||||
case CEntityOrder::ORDER_GOTO:
|
||||
{
|
||||
context.m_data[0].location = g_Mouseover.m_worldposition;
|
||||
break;
|
||||
/*
|
||||
CGotoCommand *msg=new CGotoCommand();
|
||||
msg->m_Entity=m_selected[0]->me;
|
||||
msg->m_TargetX=(u32)g_Mouseover.m_worldposition.x;
|
||||
msg->m_TargetY=(u32)g_Mouseover.m_worldposition.y;
|
||||
g_Game->GetSimulation()->QueueLocalCommand(msg);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
case CEntityOrder::ORDER_ATTACK_MELEE:
|
||||
{
|
||||
context.m_data[0].entity = g_Mouseover.m_target;
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
if( (*it)->acceptsOrder( m_contextOrder, g_Mouseover.m_target ) )
|
||||
{
|
||||
if( !pushQueue )
|
||||
(*it)->clearOrders();
|
||||
(*it)->pushOrder( context );
|
||||
}
|
||||
return;
|
||||
}
|
||||
case CEntityOrder::ORDER_GATHER:
|
||||
{
|
||||
context.m_data[0].entity = g_Mouseover.m_target;
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
if( (*it)->acceptsOrder( m_contextOrder, g_Mouseover.m_target ) )
|
||||
{
|
||||
if( !pushQueue )
|
||||
(*it)->clearOrders();
|
||||
(*it)->pushOrder( context );
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Location randomizer, for group orders...
|
||||
// Having the group turn up at the destination with /some/ sort of cohesion is good
|
||||
// but tasking them all to the exact same point will leave them brawling for it
|
||||
// at the other end (it shouldn't, but the PASAP pathfinder is too simplistic)
|
||||
|
||||
// Task them all to a point within a radius of the target, radius depends upon
|
||||
// the number of units in the group.
|
||||
|
||||
/* (Simon)
|
||||
Hmm. Disabled in the makeshift transition to Command Message Queueing...
|
||||
|
||||
Ideally, we'd create a Group with the selected entities, then queue a
|
||||
command with the Group ID as performing entity, with the center as the
|
||||
target, then let the location randomization be done in the
|
||||
net command=>ent. order translator (for now, CSimulation::TranslateMessage)
|
||||
|
||||
Unless this is a problem that'll only be around until we make the real
|
||||
pathfinder?
|
||||
*/
|
||||
|
||||
float radius = 2.0f * sqrt( (float)m_selected.size() - 1 );
|
||||
|
||||
float _x, _y;
|
||||
|
||||
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
if( ( (*it)->GetPlayer() == g_Game->GetLocalPlayer() ) &&
|
||||
( (*it)->acceptsOrder( m_contextOrder, g_Mouseover.m_target ) ) )
|
||||
{
|
||||
contextRandomized = context;
|
||||
do
|
||||
{
|
||||
_x = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
|
||||
_y = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
|
||||
}
|
||||
while( ( _x * _x ) + ( _y * _y ) > 1.0f );
|
||||
|
||||
contextRandomized.m_data[0].location.x += _x * radius;
|
||||
contextRandomized.m_data[0].location.y += _y * radius;
|
||||
|
||||
// Clamp it to within the map, just in case.
|
||||
float mapsize = (float)g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide() * CELL_SIZE;
|
||||
|
||||
if( contextRandomized.m_data[0].location.x < 0.0f )
|
||||
contextRandomized.m_data[0].location.x = 0.0f;
|
||||
if( contextRandomized.m_data[0].location.x >= mapsize )
|
||||
contextRandomized.m_data[0].location.x = mapsize;
|
||||
if( contextRandomized.m_data[0].location.y < 0.0f )
|
||||
contextRandomized.m_data[0].location.y = 0.0f;
|
||||
if( contextRandomized.m_data[0].location.y >= mapsize )
|
||||
contextRandomized.m_data[0].location.y = mapsize;
|
||||
|
||||
if( !pushQueue )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( contextRandomized );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CMouseoverEntities::update( float timestep )
|
||||
{
|
||||
CCamera *pCamera=g_Game->GetView()->GetCamera();
|
||||
@ -881,6 +721,58 @@ void CMouseoverEntities::stopBandbox()
|
||||
m_bandbox = false;
|
||||
}
|
||||
|
||||
void FireWorldClickEvent(uint button, int clicks)
|
||||
{
|
||||
debug_printf("FireWorldClickEvent: button %d, clicks %d\n", button, clicks);
|
||||
g_JSGameEvents.FireWorldClick(
|
||||
button,
|
||||
clicks,
|
||||
g_Selection.m_defaultCommand,
|
||||
-1, // FIXME Secondary command, depends entity scripts etc
|
||||
g_Mouseover.m_target,
|
||||
(uint)g_Mouseover.m_worldposition.x,
|
||||
(uint)g_Mouseover.m_worldposition.y);
|
||||
}
|
||||
|
||||
void MouseButtonUpHandler(const SDL_Event *ev, int clicks)
|
||||
{
|
||||
FireWorldClickEvent(ev->button.button, clicks);
|
||||
|
||||
switch( ev->button.button )
|
||||
{
|
||||
case SDL_BUTTON_LEFT:
|
||||
if (customSelectionMode)
|
||||
break;
|
||||
|
||||
if( g_Mouseover.m_viewall )
|
||||
break;
|
||||
|
||||
if( clicks == 2 )
|
||||
{
|
||||
// Double click
|
||||
g_Mouseover.expandAcrossScreen();
|
||||
}
|
||||
else if( clicks == 3 )
|
||||
{
|
||||
// Triple click
|
||||
g_Mouseover.expandAcrossWorld();
|
||||
}
|
||||
|
||||
g_Mouseover.stopBandbox();
|
||||
if( hotkeys[HOTKEY_SELECTION_ADD] )
|
||||
{
|
||||
g_Mouseover.addSelection();
|
||||
}
|
||||
else if( hotkeys[HOTKEY_SELECTION_REMOVE] )
|
||||
{
|
||||
g_Mouseover.removeSelection();
|
||||
}
|
||||
else
|
||||
g_Mouseover.setSelection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int interactInputHandler( const SDL_Event* ev )
|
||||
{
|
||||
if (!g_active || !g_Game)
|
||||
@ -890,13 +782,19 @@ int interactInputHandler( const SDL_Event* ev )
|
||||
CCamera *pCamera=pView->GetCamera();
|
||||
CTerrain *pTerrain=g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
static float lastclicktime = 0.0f;
|
||||
static HEntity lastclickobject;
|
||||
static u8 clicks = 0;
|
||||
// One entry for each of five mouse buttons (SDL mouse buttons 1-5, mouse
|
||||
// buttons over 5 if existant, will be ignored)
|
||||
static float lastclicktime[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
static HEntity lastclickobject[5];
|
||||
static u8 clicks[5] = {0, 0, 0, 0, 0};
|
||||
|
||||
static u16 button_down_x, button_down_y;
|
||||
static float button_down_time;
|
||||
static bool button_down = false;
|
||||
|
||||
if (customSelectionMode && ev->type != SDL_MOUSEBUTTONUP)
|
||||
return EV_PASS;
|
||||
|
||||
switch( ev->type )
|
||||
{
|
||||
case SDL_HOTKEYDOWN:
|
||||
@ -909,12 +807,6 @@ int interactInputHandler( const SDL_Event* ev )
|
||||
if( g_Selection.m_selected.size() )
|
||||
pView->SetCameraTarget( g_Selection.getSelectionPosition() );
|
||||
break;
|
||||
case HOTKEY_CONTEXTORDER_NEXT:
|
||||
g_Selection.nextContext();
|
||||
break;
|
||||
case HOTKEY_CONTEXTORDER_PREVIOUS:
|
||||
g_Selection.previousContext();
|
||||
break;
|
||||
default:
|
||||
if( ( ev->user.code >= HOTKEY_SELECTION_GROUP_0 ) && ( ev->user.code <= HOTKEY_SELECTION_GROUP_19 ) )
|
||||
{
|
||||
@ -964,53 +856,34 @@ int interactInputHandler( const SDL_Event* ev )
|
||||
}
|
||||
return( EV_HANDLED );
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
switch( ev->button.button )
|
||||
{
|
||||
case SDL_BUTTON_LEFT:
|
||||
if( g_Mouseover.m_viewall )
|
||||
break;
|
||||
// Assumes SDL button enums in range [1, 5]
|
||||
int button = ev->button.button - 1;
|
||||
// Only process buttons within the range for which we have button state
|
||||
// arrays above.
|
||||
if (button >= 0 && button < 5)
|
||||
{
|
||||
float time;
|
||||
time = (float)get_time();
|
||||
// Reset clicks counter if too slow or if the cursor's
|
||||
// hovering over something else now.
|
||||
|
||||
if( time - lastclicktime >= SELECT_DBLCLICK_RATE )
|
||||
clicks = 0;
|
||||
if( g_Mouseover.m_target != lastclickobject )
|
||||
clicks = 0;
|
||||
clicks++;
|
||||
if( time - lastclicktime[button] >= SELECT_DBLCLICK_RATE )
|
||||
clicks[button] = 0;
|
||||
if( g_Mouseover.m_target != lastclickobject[button] )
|
||||
clicks[button] = 0;
|
||||
clicks[button]++;
|
||||
|
||||
if( clicks == 2 )
|
||||
{
|
||||
// Double click
|
||||
g_Mouseover.expandAcrossScreen();
|
||||
}
|
||||
else if( clicks == 3 )
|
||||
{
|
||||
// Triple click
|
||||
g_Mouseover.expandAcrossWorld();
|
||||
}
|
||||
lastclicktime = time;
|
||||
lastclickobject = g_Mouseover.m_target;
|
||||
lastclicktime[button] = time;
|
||||
lastclickobject[button] = g_Mouseover.m_target;
|
||||
|
||||
if (ev->button.button == SDL_BUTTON_LEFT)
|
||||
button_down = false;
|
||||
g_Mouseover.stopBandbox();
|
||||
if( hotkeys[HOTKEY_SELECTION_ADD] )
|
||||
{
|
||||
g_Mouseover.addSelection();
|
||||
}
|
||||
else if( hotkeys[HOTKEY_SELECTION_REMOVE] )
|
||||
{
|
||||
g_Mouseover.removeSelection();
|
||||
}
|
||||
else
|
||||
g_Mouseover.setSelection();
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
g_Selection.contextOrder( hotkeys[HOTKEY_ORDER_QUEUE] );
|
||||
break;
|
||||
|
||||
MouseButtonUpHandler(ev, clicks[button]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
switch( ev->button.button )
|
||||
{
|
||||
@ -1018,6 +891,7 @@ int interactInputHandler( const SDL_Event* ev )
|
||||
button_down = true;
|
||||
button_down_x = ev->button.x;
|
||||
button_down_y = ev->button.y;
|
||||
button_down_time = get_time();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1057,3 +931,13 @@ bool isMouseoverType( CEntity* ev, void* userdata )
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
|
||||
void StartCustomSelection()
|
||||
{
|
||||
customSelectionMode = true;
|
||||
}
|
||||
|
||||
void ResetInteraction()
|
||||
{
|
||||
customSelectionMode = false;
|
||||
}
|
||||
|
@ -29,14 +29,14 @@ struct CSelectedEntities : public Singleton<CSelectedEntities>
|
||||
clearSelection();
|
||||
m_group = -1;
|
||||
m_group_highlight = -1;
|
||||
m_contextOrder = -1;
|
||||
m_defaultCommand = -1;
|
||||
m_selectionChanged = true;
|
||||
}
|
||||
std::vector<HEntity> m_selected;
|
||||
std::vector<HEntity> m_groups[MAX_GROUPS];
|
||||
i8 m_group, m_group_highlight;
|
||||
bool m_selectionChanged;
|
||||
int m_contextOrder;
|
||||
int m_defaultCommand;
|
||||
|
||||
void addSelection( HEntity entity );
|
||||
void removeSelection( HEntity entity );
|
||||
@ -57,11 +57,6 @@ struct CSelectedEntities : public Singleton<CSelectedEntities>
|
||||
CVector3D getGroupPosition( i8 groupid );
|
||||
|
||||
void update();
|
||||
bool isContextValid( int contextOrder );
|
||||
void contextOrder( bool pushQueue = false );
|
||||
void setContext( int contextOrder );
|
||||
bool nextContext();
|
||||
bool previousContext();
|
||||
|
||||
void renderSelectionOutlines();
|
||||
void renderOverlays();
|
||||
@ -121,6 +116,9 @@ struct CMouseoverEntities : public Singleton<CMouseoverEntities>
|
||||
bool isMouseoverType( CEntity* ev, void* userdata );
|
||||
bool isOnScreen( CEntity* ev, void* userdata );
|
||||
|
||||
void StartCustomSelection();
|
||||
void ResetInteraction();
|
||||
|
||||
int interactInputHandler( const SDL_Event* ev );
|
||||
|
||||
#define g_Selection CSelectedEntities::GetSingleton()
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include "lib.h" // error codes
|
||||
#include "timer.h"
|
||||
@ -66,7 +66,7 @@ struct LoadRequest
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::deque<const LoadRequest> LoadRequests;
|
||||
typedef std::deque<LoadRequest> LoadRequests;
|
||||
static LoadRequests load_requests;
|
||||
|
||||
// std::accumulate binary op; used by LDR_EndRegistering to sum up all
|
||||
|
@ -56,9 +56,12 @@ enum ENetMessageType
|
||||
NMT_StartGame,
|
||||
/* In-Game Stage */
|
||||
NMT_EndCommandBatch,
|
||||
NMT_COMMAND_FIRST,
|
||||
NMT_GotoCommand=NMT_COMMAND_FIRST,
|
||||
NMT_COMMAND_LAST=NMT_GotoCommand,
|
||||
NMT_Goto, NMT_COMMAND_FIRST=NMT_Goto,
|
||||
NMT_Patrol,
|
||||
NMT_AddWaypoint,
|
||||
NMT_AttackMelee,
|
||||
NMT_Gather,
|
||||
NMT_COMMAND_LAST,
|
||||
/* Post-Game Stage */
|
||||
|
||||
/**
|
||||
@ -120,6 +123,7 @@ enum
|
||||
|
||||
#define ALLNETMSGS_DONT_CREATE_NMTS
|
||||
#define START_NMT_CLASS_(_nm) START_NMT_CLASS(C ## _nm, NMT_ ## _nm)
|
||||
#define DERIVE_NMT_CLASS_(_base, _nm) START_NMT_CLASS_DERIVED(C ## _base, C ## _nm, NMT_ ## _nm)
|
||||
|
||||
START_NMTS()
|
||||
|
||||
@ -198,24 +202,32 @@ START_NMT_CLASS_(EndCommandBatch)
|
||||
NMT_FIELD_INT(m_TurnLength, u32, 2)
|
||||
END_NMT_CLASS()
|
||||
|
||||
START_NMT_CLASS_(GotoCommand)
|
||||
NMT_FIELD(HEntity, m_Entity)
|
||||
START_NMT_CLASS(CCommand, NMT_NONE)
|
||||
NMT_FIELD(CEntityList, m_Entities)
|
||||
END_NMT_CLASS()
|
||||
|
||||
DERIVE_NMT_CLASS_(Command, Goto)
|
||||
NMT_FIELD_INT(m_TargetX, u32, 2)
|
||||
NMT_FIELD_INT(m_TargetY, u32, 2)
|
||||
END_NMT_CLASS()
|
||||
|
||||
/*
|
||||
#define NMT_FIELD_MAPPOS(_nm) NMT_FIELD_INT(_nm##X, u32, 2) NMT_FIELD_INT(_nm##Y, u32, 2)
|
||||
|
||||
START_NMT_CLASS_(SetWaypoint)
|
||||
NMT_FIELD(HEntity, m_Entity)
|
||||
NMT_FIELD_MAPPOS(m_Target)
|
||||
DERIVE_NMT_CLASS_(Command, Patrol)
|
||||
NMT_FIELD_INT(m_TargetX, u32, 2)
|
||||
NMT_FIELD_INT(m_TargetY, u32, 2)
|
||||
END_NMT_CLASS()
|
||||
|
||||
START_NMT_CLASS_(AddWaypoint)
|
||||
NMT_FIELD(HEntity, m_Entity)
|
||||
NMT_FIELD_MAPPOS(m_Target)
|
||||
END_NMY_CLASS()*/
|
||||
DERIVE_NMT_CLASS_(Command, AddWaypoint)
|
||||
NMT_FIELD_INT(m_TargetX, u32, 2)
|
||||
NMT_FIELD_INT(m_TargetY, u32, 2)
|
||||
END_NMT_CLASS()
|
||||
|
||||
DERIVE_NMT_CLASS_(Command, AttackMelee)
|
||||
NMT_FIELD(HEntity, m_Target)
|
||||
END_NMT_CLASS()
|
||||
|
||||
DERIVE_NMT_CLASS_(Command, Gather)
|
||||
NMT_FIELD(HEntity, m_Target)
|
||||
END_NMT_CLASS()
|
||||
|
||||
END_NMTS()
|
||||
|
||||
|
@ -324,7 +324,7 @@ bool CNetClient::InGameHandler(CNetMessage *pMsg, CNetSession *pSession)
|
||||
CHAIN(BaseHandler);
|
||||
CHAIN(ChatHandler);
|
||||
|
||||
if (msgType >= NMT_COMMAND_FIRST && msgType <= NMT_COMMAND_LAST)
|
||||
if (msgType >= NMT_COMMAND_FIRST && msgType < NMT_COMMAND_LAST)
|
||||
{
|
||||
pClient->QueueMessage(1, pMsg);
|
||||
TAKEN(pMsg);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#undef START_NMTS
|
||||
#undef END_NMTS
|
||||
#undef START_NMT_CLASS
|
||||
#undef START_NMT_CLASS_DERIVED
|
||||
#undef NMT_FIELD_INT
|
||||
#undef NMT_FIELD
|
||||
#undef NMT_START_ARRAY
|
||||
@ -32,18 +33,29 @@
|
||||
#define START_NMTS()
|
||||
#define END_NMTS()
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
|
||||
|
||||
/**
|
||||
* Start the definition of a network message type.
|
||||
*
|
||||
* @param _base The name of the base class of the message
|
||||
* @param _nm The name of the class
|
||||
* @param _tp The NetMessageType associated with the class. It is *not* safe to
|
||||
* have several classes with the same value of _tp in the same executable
|
||||
*/
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
CNetMessage *Deserialize##_nm(const u8 *, uint); \
|
||||
struct _nm: public CNetMessage \
|
||||
class _nm: public _base \
|
||||
{ \
|
||||
_nm(): CNetMessage(_tp) {} \
|
||||
protected: \
|
||||
_nm(ENetMessageType type): _base(type) {}\
|
||||
\
|
||||
/* This one is for subclasses that want to use the base class' string */ \
|
||||
/* converters to get SubMessage { <parent fields>, ... } */ \
|
||||
CStr GetStringRaw() const;\
|
||||
public: \
|
||||
_nm(): _base(_tp) {} \
|
||||
virtual uint GetSerializedLength() const; \
|
||||
virtual u8 *Serialize(u8 *buffer) const; \
|
||||
virtual const u8 *Deserialize(const u8 *pos, const u8 *end); \
|
||||
@ -103,9 +115,11 @@ struct _nm: public CNetMessage \
|
||||
#define END_NMTS()
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
uint _nm::GetSerializedLength() const \
|
||||
{ \
|
||||
uint ret=0; \
|
||||
uint ret=_base::GetSerializedLength(); \
|
||||
const _nm *thiz=this;
|
||||
|
||||
#define NMT_START_ARRAY(_nm) \
|
||||
@ -140,10 +154,12 @@ uint _nm::GetSerializedLength() const \
|
||||
#define END_NMTS()
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
u8 *_nm::Serialize(u8 *buffer) const \
|
||||
{ \
|
||||
/*printf("In " #_nm "::Serialize()\n");*/ \
|
||||
u8 *pos=buffer; \
|
||||
u8 *pos=_base::Serialize(buffer); \
|
||||
const _nm *thiz=this;
|
||||
|
||||
#define NMT_START_ARRAY(_nm) \
|
||||
@ -181,6 +197,8 @@ u8 *_nm::Serialize(u8 *buffer) const \
|
||||
#define BAIL_DESERIALIZER return NULL
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
CNetMessage *Deserialize##_nm(const u8 *buffer, uint length) \
|
||||
{ \
|
||||
_nm *ret=new _nm(); \
|
||||
@ -191,6 +209,7 @@ CNetMessage *Deserialize##_nm(const u8 *buffer, uint length) \
|
||||
} \
|
||||
const u8 *_nm::Deserialize(const u8 *pos, const u8 *end) \
|
||||
{ \
|
||||
pos=_base::Deserialize(pos, end); \
|
||||
_nm *thiz=this; \
|
||||
/*printf("In Deserialize" #_nm "\n"); */
|
||||
|
||||
@ -229,6 +248,8 @@ const u8 *_nm::Deserialize(const u8 *pos, const u8 *end) \
|
||||
#define END_NMTS() { NMT_NONE, NULL } };
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
{ _tp, Deserialize##_nm },
|
||||
|
||||
#define NMT_START_ARRAY(_nm)
|
||||
@ -254,6 +275,22 @@ const u8 *_nm::Deserialize(const u8 *pos, const u8 *end) \
|
||||
CStr _nm::GetString() const \
|
||||
{ \
|
||||
CStr ret=#_nm _T(" { "); \
|
||||
return ret + GetStringRaw() + _T(" }"); \
|
||||
} \
|
||||
CStr _nm::GetStringRaw() const \
|
||||
{ \
|
||||
CStr ret; \
|
||||
const _nm *thiz=this;
|
||||
|
||||
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
|
||||
CStr _nm::GetString() const \
|
||||
{ \
|
||||
CStr ret=#_nm _T(" { "); \
|
||||
return ret + GetStringRaw() + _T(" }"); \
|
||||
} \
|
||||
CStr _nm::GetStringRaw() const \
|
||||
{ \
|
||||
CStr ret=_base::GetStringRaw() + _T(", "); \
|
||||
const _nm *thiz=this;
|
||||
|
||||
#define NMT_START_ARRAY(_nm) \
|
||||
@ -281,7 +318,7 @@ CStr _nm::GetString() const \
|
||||
ret += _T(", ");
|
||||
|
||||
#define END_NMT_CLASS() \
|
||||
return ret.GetSubstring(0, ret.Length()-2)+_T(" }"); \
|
||||
return ret.GetSubstring(0, ret.Length()-2); \
|
||||
}
|
||||
|
||||
#include "NMTCreator.h"
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
#define ALLNETMSGS_IMPLEMENT
|
||||
|
||||
#include "NetMessage.h"
|
||||
@ -69,3 +71,98 @@ CNetMessage *CNetMessage::DeserializeMessage(ENetMessageType type, u8 *buffer, u
|
||||
return (pDes)(buffer, length);
|
||||
}
|
||||
|
||||
void CNetMessage::ScriptingInit()
|
||||
{
|
||||
#define def(_msg) g_ScriptingHost.DefineConstant(#_msg, _msg)
|
||||
|
||||
def(NMT_Goto);
|
||||
def(NMT_Patrol);
|
||||
def(NMT_AddWaypoint);
|
||||
def(NMT_AttackMelee);
|
||||
def(NMT_Gather);
|
||||
}
|
||||
|
||||
CCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSContext *cx, uintN argc, jsval *argv)
|
||||
{
|
||||
assert(argc >= 1);
|
||||
|
||||
int msgType;
|
||||
|
||||
try
|
||||
{
|
||||
msgType = g_ScriptingHost.ValueToInt( argv[0] );
|
||||
}
|
||||
catch(PSERROR_Scripting_ConversionFailed)
|
||||
{
|
||||
JS_ReportError(cx, "Invalid order type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define ArgumentCountError() STMT(\
|
||||
JS_ReportError(cx, "Too few parameters!"); \
|
||||
return NULL; )
|
||||
#define ArgumentTypeError() STMT(\
|
||||
JS_ReportError(cx, "Parameter type error!"); \
|
||||
return NULL; )
|
||||
#define ReadPosition(_msg, _field) \
|
||||
try { \
|
||||
if (argIndex+2 > argc) \
|
||||
ArgumentCountError();\
|
||||
if (!JSVAL_IS_INT(argv[argIndex]) || !JSVAL_IS_INT(argv[argIndex+1])) \
|
||||
ArgumentTypeError(); \
|
||||
_msg->_field ## X = g_ScriptingHost.ValueToInt(argv[argIndex++]); \
|
||||
_msg->_field ## Y = g_ScriptingHost.ValueToInt(argv[argIndex++]); \
|
||||
} catch (PSERROR_Scripting_ConversionFailed) { \
|
||||
JS_ReportError(cx, "Invalid location"); \
|
||||
return NULL; \
|
||||
}
|
||||
#define ReadEntity(_msg, _field) \
|
||||
STMT(\
|
||||
if (argIndex+1 > argc) \
|
||||
ArgumentCountError(); \
|
||||
if (!JSVAL_IS_OBJECT(argv[argIndex])) \
|
||||
ArgumentTypeError(); \
|
||||
CEntity *ent=ToNative<CEntity>(argv[argIndex++]); \
|
||||
if (!ent) \
|
||||
{ \
|
||||
JS_ReportError(cx, "Invalid entity parameter"); \
|
||||
return NULL; \
|
||||
} \
|
||||
_msg->_field=ent->me; \
|
||||
)
|
||||
|
||||
#define PositionMessage(_msg) \
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_Entities = entities; \
|
||||
ReadPosition(msg, m_Target); \
|
||||
return msg; \
|
||||
}
|
||||
|
||||
#define EntityMessage(_msg) \
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_Entities = entities; \
|
||||
ReadEntity(msg, m_Target); \
|
||||
return msg; \
|
||||
}
|
||||
|
||||
// argIndex, incremented by reading macros. We have already "eaten" the
|
||||
// first argument (message type)
|
||||
uint argIndex = 1;
|
||||
switch (msgType)
|
||||
{
|
||||
// NMT_Goto, targetX, targetY
|
||||
PositionMessage(Goto)
|
||||
PositionMessage(Patrol)
|
||||
PositionMessage(AddWaypoint)
|
||||
|
||||
EntityMessage(AttackMelee)
|
||||
EntityMessage(Gather)
|
||||
default:
|
||||
JS_ReportError(cx, "Invalid order type");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "AllNetMessages.h"
|
||||
#undef ALLNETMSGS_DONT_CREATE_NMTS
|
||||
|
||||
class CCommand;
|
||||
class CEntityList;
|
||||
|
||||
/**
|
||||
* The base class for network messages
|
||||
*/
|
||||
@ -63,6 +66,14 @@ public:
|
||||
* there was an error in data format.
|
||||
*/
|
||||
static CNetMessage *DeserializeMessage(ENetMessageType type, u8 *buffer, uint length);
|
||||
|
||||
/**
|
||||
* Register a selection of message types as JS constants.
|
||||
* The constant's names will be the same as those of the enums
|
||||
*/
|
||||
static void ScriptingInit();
|
||||
|
||||
static CCommand *CommandFromJSArgs(const CEntityList &entities, JSContext* cx, uintN argc, jsval* argv);
|
||||
};
|
||||
|
||||
typedef CNetMessage * (*NetMessageDeserializer) (const u8 *buffer, uint length);
|
||||
|
@ -182,7 +182,7 @@ bool CNetServerSession::InGameHandler(CNetMessage *pMsg, CNetSession *pNetSessio
|
||||
if (ChatHandler(pMsg, pNetSession))
|
||||
return true;
|
||||
|
||||
if (pMsg->GetType() >= NMT_COMMAND_FIRST && pMsg->GetType() <= NMT_COMMAND_LAST)
|
||||
if (pMsg->GetType() >= NMT_COMMAND_FIRST && pMsg->GetType() < NMT_COMMAND_LAST)
|
||||
{
|
||||
// All Command Messages (i.e. simulation turn synchronized messages)
|
||||
//pSession->m_pPlayer->ValidateCommand(pMsg);
|
||||
|
@ -40,7 +40,7 @@ void CPlayer::ScriptingInit()
|
||||
|
||||
// AddClassProperty( L"name", &CPlayer::m_Name );
|
||||
// AddClassProperty( L"colour", &CPlayer::m_Colour );
|
||||
AddProperty( L"controlled", (IJSObject::GetFn)JSI_GetControlledEntities );
|
||||
AddProperty( L"controlled", (IJSObject::GetFn)&CPlayer::JSI_GetControlledEntities );
|
||||
|
||||
CJSObject<CPlayer>::ScriptingInit( "Player" );
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ bool CProfileNode::Return()
|
||||
|
||||
void CProfileNode::ScriptingInit()
|
||||
{
|
||||
AddProperty( L"name", (IJSObject::GetFn)CProfileNode::JS_GetName );
|
||||
AddProperty( L"name", (IJSObject::GetFn)&CProfileNode::JS_GetName );
|
||||
/*
|
||||
AddReadOnlyClassProperty( L"callsTotal", &CProfileNode::calls_total );
|
||||
AddReadOnlyClassProperty( L"callsPerFrame", &CProfileNode::calls_frame_last );
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "CLogger.h"
|
||||
#define LOG_CATEGORY "vfs"
|
||||
|
||||
#include <deque>
|
||||
|
||||
using namespace VFSUtil;
|
||||
|
||||
// Because I'm lazy, and it saves a few lines of code in other places:
|
||||
@ -73,7 +75,7 @@ int VFSUtil::EnumDirEnts(const CStr start_path, const char* user_filter,
|
||||
// (less stack usage; avoids seeks by reading all entries in a
|
||||
// directory consecutively)
|
||||
|
||||
std::deque<const CStr> dir_queue;
|
||||
std::deque<CStr> dir_queue;
|
||||
dir_queue.push_back(start_path);
|
||||
|
||||
// for each directory:
|
||||
|
@ -283,7 +283,7 @@ template<typename T, JSClass* ScriptType> JSBool CJSCollection<T, ScriptType>::E
|
||||
std::vector<T>* b = RetrieveSet( cx, JSVAL_TO_OBJECT( argv[0] ) );
|
||||
if( !b )
|
||||
return( JS_FALSE );
|
||||
std::vector<T>::iterator ita, itb;
|
||||
typename std::vector<T>::iterator ita, itb;
|
||||
|
||||
size_t seek = a->size();
|
||||
for( ita = a->begin(); ita != a->end(); ita++ )
|
||||
|
@ -91,48 +91,3 @@ JSBool JSI_Selection::setGroups( JSContext* context, JSObject* obj, jsval id, js
|
||||
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_Selection::isValidContextOrder( JSContext* context, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
assert( argc >= 1 );
|
||||
int orderCode;
|
||||
try
|
||||
{
|
||||
orderCode = g_ScriptingHost.ValueToInt( argv[0] );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
JS_ReportError( context, "Invalid order type" );
|
||||
*rval = BOOLEAN_TO_JSVAL( false );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
*rval = BOOLEAN_TO_JSVAL( g_Selection.isContextValid( orderCode ) );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_Selection::getContextOrder( JSContext* context, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
*vp = INT_TO_JSVAL( g_Selection.m_contextOrder );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_Selection::setContextOrder( JSContext* context, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
int orderCode;
|
||||
try
|
||||
{
|
||||
orderCode = g_ScriptingHost.ValueToInt( *vp );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
JS_ReportError( context, "Invalid order type" );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
if( !g_Selection.isContextValid( orderCode ) )
|
||||
{
|
||||
JS_ReportError( context, "Order is not valid in this context: %d", orderCode );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
g_Selection.setContext( orderCode );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/VFSUtil.h"
|
||||
#include "lib/res/res.h"
|
||||
@ -7,7 +9,6 @@
|
||||
#include "scripting/JSConversions.h"
|
||||
#include "scripting/JSInterface_VFS.h"
|
||||
|
||||
|
||||
// shared error handling code
|
||||
#define JS_CHECK_FILE_ERR(err)\
|
||||
/* this is liable to happen often, so don't complain */\
|
||||
|
@ -148,7 +148,7 @@ void CScriptEvent::ScriptingInit()
|
||||
AddMethod<jsval, &CScriptEvent::ToString>( "toString", 0 );
|
||||
AddMethod<jsval, &CScriptEvent::PreventDefault>( "preventDefault", 0 );
|
||||
AddMethod<jsval, &CScriptEvent::PreventDefault>( "cancel", 0 );
|
||||
AddMethod<jsval, StopPropagation>( "stopPropagation", 0 );
|
||||
AddMethod<jsval, &CScriptEvent::StopPropagation>( "stopPropagation", 0 );
|
||||
|
||||
AddProperty( L"type", &CScriptEvent::m_Type, true );
|
||||
AddProperty( L"cancelable", &CScriptEvent::m_Cancelable, true );
|
||||
|
@ -20,6 +20,7 @@ enum EEventType
|
||||
EVENT_GAME_START = 0,
|
||||
EVENT_GAME_TICK,
|
||||
EVENT_SELECTION_CHANGED,
|
||||
EVENT_WORLD_CLICK,
|
||||
};
|
||||
|
||||
// Only used for entity events...
|
||||
|
@ -18,18 +18,58 @@ class CGameEvents : public IEventTarget, public Singleton<CGameEvents>
|
||||
{
|
||||
bool m_CausedByPlayer;
|
||||
public:
|
||||
CEventSelectionChanged( bool CausedByPlayer ) : CScriptEvent( L"selectionChanged", EVENT_SELECTION_CHANGED, false )
|
||||
CEventSelectionChanged(bool CausedByPlayer):
|
||||
CScriptEvent( L"selectionChanged", EVENT_SELECTION_CHANGED, false ),
|
||||
m_CausedByPlayer(CausedByPlayer)
|
||||
{
|
||||
AddLocalProperty( L"byPlayer", &m_CausedByPlayer, true );
|
||||
}
|
||||
};
|
||||
|
||||
class CEventWorldClick: public CScriptEvent
|
||||
{
|
||||
int m_Button;
|
||||
int m_Clicks;
|
||||
int m_Command;
|
||||
int m_SecondaryCommand;
|
||||
CEntity *m_Entity;
|
||||
uint m_X, m_Y;
|
||||
public:
|
||||
CEventWorldClick(int button, int clicks, int command, int secCommand, CEntity *ent, uint x, uint y):
|
||||
CScriptEvent(L"worldClick", EVENT_WORLD_CLICK, false),
|
||||
m_Button(button),
|
||||
m_Clicks(clicks),
|
||||
m_Command(command),
|
||||
m_SecondaryCommand(secCommand),
|
||||
m_Entity(ent),
|
||||
m_X(x),
|
||||
m_Y(y)
|
||||
{
|
||||
AddLocalProperty(L"button", &m_Button);
|
||||
AddLocalProperty(L"clicks", &m_Clicks);
|
||||
AddLocalProperty(L"command", &m_Command);
|
||||
AddLocalProperty(L"secondaryCommand", &m_SecondaryCommand);
|
||||
if (ent)
|
||||
AddLocalProperty(L"entity", &m_Entity);
|
||||
else
|
||||
AddProperty(L"entity", JSVAL_NULL);
|
||||
AddLocalProperty(L"x", &m_X);
|
||||
AddLocalProperty(L"y", &m_Y);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void FireSelectionChanged( bool CausedByPlayer )
|
||||
{
|
||||
CEventSelectionChanged evt( CausedByPlayer );
|
||||
DispatchEvent( &evt );
|
||||
}
|
||||
|
||||
void FireWorldClick(int button, int clicks, int command, int secCommand, CEntity *ent, uint x, uint y)
|
||||
{
|
||||
CEventWorldClick evt(button, clicks, command, secCommand, ent, x, y);
|
||||
DispatchEvent(&evt);
|
||||
}
|
||||
};
|
||||
|
||||
#define g_JSGameEvents CGameEvents::GetSingleton()
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "LightEnv.h"
|
||||
#include "MapWriter.h"
|
||||
#include "GameEvents.h"
|
||||
#include "Interact.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Network/Server.h"
|
||||
@ -82,6 +83,8 @@ JSFunctionSpec ScriptFunctionTable[] =
|
||||
|
||||
{"v3dist", v3dist, 2, 0, 0 },
|
||||
|
||||
{"issueCommand", issueCommand, 2, 0, 0 },
|
||||
|
||||
{"exit", exitProgram, 0, 0, 0 },
|
||||
{"crash", crash, 0, 0, 0 },
|
||||
{"forceGC", forceGC, 0, 0, 0 },
|
||||
@ -108,6 +111,7 @@ JSPropertySpec ScriptGlobalTable[] =
|
||||
{ "players", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetPlayerSet, NULL },
|
||||
{ "localPlayer", 0, JSPROP_PERMANENT, GetLocalPlayer, SetLocalPlayer },
|
||||
{ "gaiaPlayer", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetGaiaPlayer, NULL },
|
||||
{ "gameView", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetGameView, NULL },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@ -238,6 +242,15 @@ JSBool SetLocalPlayer( JSContext* context, JSObject* obj, jsval id, jsval* vp )
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool GetGameView( JSContext* cx, JSObject* globalObject, jsval id, jsval* vp )
|
||||
{
|
||||
if (g_Game)
|
||||
*vp = OBJECT_TO_JSVAL( g_Game->GetView()->GetScript() );
|
||||
else
|
||||
*vp = JSVAL_NULL;
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool AddGlobalHandler( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
*rval = BOOLEAN_TO_JSVAL( g_JSGameEvents.AddHandlerJS( cx, argc, argv ) );
|
||||
@ -553,3 +566,30 @@ JSBool _rewriteMaps(JSContext* UNUSEDPARAM(context), JSObject* UNUSEDPARAM(globa
|
||||
CMapWriter::RewriteAllMaps(g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetUnitManager(), &g_LightEnv);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool issueCommand(JSContext* context, JSObject* UNUSEDPARAM(globalObject), unsigned int argc, jsval* argv, jsval* rval)
|
||||
{
|
||||
assert(argc >= 2);
|
||||
assert(JSVAL_IS_OBJECT(argv[0]));
|
||||
|
||||
CEntityList entities;
|
||||
|
||||
if (JS_GetClass(JSVAL_TO_OBJECT(argv[0])) == &CEntity::JSI_class)
|
||||
entities.push_back( (ToNative<CEntity>(argv[0])) ->me);
|
||||
else
|
||||
entities = *EntityCollection::RetrieveSet(context, JSVAL_TO_OBJECT(argv[0]));
|
||||
|
||||
CNetMessage *msg=CNetMessage::CommandFromJSArgs(entities, context, argc-1, argv+1);
|
||||
if (msg)
|
||||
{
|
||||
g_Console->InsertMessage(L"issueCommand: %hs", msg->GetString().c_str());
|
||||
*rval = g_ScriptingHost.UCStringToValue(msg->GetString());
|
||||
|
||||
g_Game->GetSimulation()->QueueLocalCommand(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
*rval = JSVAL_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ JSFunc getGlobal;
|
||||
|
||||
JSFunc setCursor;
|
||||
|
||||
JSBool GetGameView( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
JSFunc GetGameObject;
|
||||
JSFunc createServer;
|
||||
JSFunc createClient;
|
||||
@ -61,6 +62,8 @@ JSFunc getFPS;
|
||||
JSFunc getCursorPosition;
|
||||
JSFunc v3dist;
|
||||
|
||||
JSFunc issueCommand;
|
||||
|
||||
// Returns a string that says when ScriptGlue.cpp was last recompiled
|
||||
JSFunc buildTime;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <jsatom.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
#ifndef SCRIPTABLE_COMPLEX_INCLUDED
|
||||
#define SCRIPTABLE_COMPLEX_INCLUDED
|
||||
|
||||
@ -958,7 +960,7 @@ template<typename T, bool ReadOnly> JSPropertySpec CJSComplex<T, ReadOnly>::JSI_
|
||||
};
|
||||
|
||||
template<typename T, bool ReadOnly> std::vector<JSFunctionSpec> CJSComplex<T, ReadOnly>::m_Methods;
|
||||
template<typename T, bool ReadOnly> typename CJSComplex<typename T, ReadOnly>::PropertyTable CJSComplex<T, ReadOnly>::m_IntrinsicProperties;
|
||||
template<typename T, bool ReadOnly> typename CJSComplex<T, ReadOnly>::PropertyTable CJSComplex<T, ReadOnly>::m_IntrinsicProperties;
|
||||
|
||||
template<typename T, bool ReadOnly> bool CJSComplex<T, ReadOnly>::GetProperty( JSContext* cx, CStrW PropertyName, jsval* vp )
|
||||
{
|
||||
|
@ -439,7 +439,7 @@ template<typename T, bool ReadOnly> JSPropertySpec CJSObject<T, ReadOnly>::JSI_p
|
||||
|
||||
template<typename T, bool ReadOnly> std::vector<JSFunctionSpec> CJSObject<T, ReadOnly>::m_Methods;
|
||||
|
||||
template<typename T, bool ReadOnly> typename CJSObject<typename T, ReadOnly>::PropertyTable CJSObject<T, ReadOnly>::m_NativeProperties;
|
||||
template<typename T, bool ReadOnly> typename CJSObject<T, ReadOnly>::PropertyTable CJSObject<T, ReadOnly>::m_NativeProperties;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -245,7 +245,7 @@ bool CBaseEntity::loadXML( CStr filename )
|
||||
CStrW EventName = L"on" + (CStrW)Child.getAttributes().getNamedItem( at_on );
|
||||
|
||||
CStrW Code (Child.getText());
|
||||
CStrW ExternalFunction = (CStrW)Child.getAttributes().getNamedItem( at_function );
|
||||
utf16string ExternalFunction = Child.getAttributes().getNamedItem( at_function );
|
||||
|
||||
// Does a property with this name already exist?
|
||||
|
||||
@ -253,10 +253,10 @@ bool CBaseEntity::loadXML( CStr filename )
|
||||
{
|
||||
if( CStrW( EventNames[eventID] ) == EventName )
|
||||
{
|
||||
if( ExternalFunction != CStrW() )
|
||||
if( ExternalFunction != utf16string() )
|
||||
{
|
||||
jsval fnval;
|
||||
JSBool ret = JS_GetUCProperty( g_ScriptingHost.GetContext(), g_ScriptingHost.GetGlobalObject(), ExternalFunction.c_str(), ExternalFunction.Length(), &fnval );
|
||||
JSBool ret = JS_GetUCProperty( g_ScriptingHost.GetContext(), g_ScriptingHost.GetGlobalObject(), ExternalFunction.c_str(), ExternalFunction.size(), &fnval );
|
||||
assert( ret );
|
||||
JSFunction* fn = JS_ValueToFunction( g_ScriptingHost.GetContext(), fnval );
|
||||
if( !fn )
|
||||
@ -346,7 +346,7 @@ void CBaseEntity::XMLLoadProperty( const CXeromyces& XeroFile, const XMBElement&
|
||||
void CBaseEntity::ScriptingInit()
|
||||
{
|
||||
AddMethod<jsval, &CBaseEntity::ToString>( "toString", 0 );
|
||||
AddClassProperty( L"traits.id.classes", (GetFn)getClassSet, (SetFn)setClassSet );
|
||||
AddClassProperty( L"traits.id.classes", (GetFn)&CBaseEntity::getClassSet, (SetFn)&CBaseEntity::setClassSet );
|
||||
|
||||
CJSComplex<CBaseEntity>::ScriptingInit( "EntityTemplate" );
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "Collision.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
CBoundingObject* getContainingObject( const CVector2D& point )
|
||||
{
|
||||
std::vector<HEntity>* entities = g_EntityManager.getExtant();
|
||||
|
@ -648,7 +648,7 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<jsval, &CEntity::GetSpawnPoint>( "getSpawnPoint", 1 );
|
||||
|
||||
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
|
||||
AddClassProperty( L"traits.id.classes", (GetFn)getClassSet, (SetFn)setClassSet );
|
||||
AddClassProperty( L"traits.id.classes", (GetFn)&CEntity::getClassSet, (SetFn)&CEntity::setClassSet );
|
||||
|
||||
CJSComplex<CEntity>::ScriptingInit( "Entity", Construct, 2 );
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
int m_lastState;
|
||||
|
||||
// Position in the current state's cycle
|
||||
static const size_t NOT_IN_CYCLE = -1;
|
||||
static const size_t NOT_IN_CYCLE = (size_t)-1;
|
||||
size_t m_fsm_cyclepos; // -cycle_length....cycle_length
|
||||
CSkeletonAnim* m_fsm_animation; // the animation we're about to play this cycle,
|
||||
size_t m_fsm_anipos; // the time at which we should start playing it.
|
||||
@ -197,6 +197,7 @@ public:
|
||||
// Script-bound functions
|
||||
|
||||
jsval ToString( JSContext* cx, uintN argc, jsval* argv );
|
||||
|
||||
bool Order( JSContext* cx, uintN argc, jsval* argv, bool Queued );
|
||||
inline bool OrderSingle( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
|
@ -129,3 +129,57 @@ HEntity::operator CStr() const
|
||||
sprintf(buf, "Entity#%04x", m_handle);
|
||||
return CStr(buf);
|
||||
}
|
||||
|
||||
uint CEntityList::GetSerializedLength() const
|
||||
{
|
||||
return 2*size();
|
||||
}
|
||||
|
||||
u8 *CEntityList::Serialize(u8 *buffer) const
|
||||
{
|
||||
for (int i=0;i<size();i++)
|
||||
Serialize_int_2(buffer, at(i).m_handle);
|
||||
Serialize_int_2(buffer, back().m_handle | HANDLE_SENTINEL_BIT);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const u8 *CEntityList::Deserialize(const u8 *buffer, const u8 *end)
|
||||
{
|
||||
u16 n=0, handle;
|
||||
while (!(n & HANDLE_SENTINEL_BIT))
|
||||
{
|
||||
Deserialize_int_2(buffer, n);
|
||||
handle = n & ~HANDLE_SENTINEL_BIT;
|
||||
// We have to validate the data, or the HEntity constructor will assert
|
||||
// on us.
|
||||
// FIXME 4096 shouldn't be hard-coded
|
||||
// FIXME We should also check that the entity actually exists
|
||||
if (handle < 4096 && handle != INVALID_HANDLE)
|
||||
push_back(HEntity(handle));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
CEntityList::operator CStr() const
|
||||
{
|
||||
if (size() == 0)
|
||||
{
|
||||
return CStr("Entities {}");
|
||||
}
|
||||
else if (size() == 1)
|
||||
{
|
||||
return front().operator CStr();
|
||||
}
|
||||
else
|
||||
{
|
||||
CStr buf="{ ";
|
||||
buf += front().operator CStr();
|
||||
for (const_iterator it=begin();it != end();++it)
|
||||
{
|
||||
buf += ", ";
|
||||
buf += it->operator CStr();
|
||||
}
|
||||
buf += " }";
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,16 @@
|
||||
#include "Network/Serialization.h"
|
||||
|
||||
#define INVALID_HANDLE 65535
|
||||
// The maximum numerical value of an entity handle sent over the network
|
||||
#define MAX_HANDLE 0x7fff
|
||||
// If (handle & PS_ENTITY_SENTINEL_BIT) is non-zero, this is a terminating
|
||||
// entity id. Reset the sentinel bit to get the original handle.
|
||||
#define HANDLE_SENTINEL_BIT 0x8000
|
||||
|
||||
|
||||
class CEntity;
|
||||
class CEntityManager;
|
||||
class CEntityList;
|
||||
class CStr8;
|
||||
|
||||
class CHandle
|
||||
@ -40,6 +47,7 @@ public:
|
||||
class HEntity
|
||||
{
|
||||
friend class CEntityManager;
|
||||
friend class CEntityList;
|
||||
u16 m_handle;
|
||||
private:
|
||||
void addRef();
|
||||
@ -64,4 +72,35 @@ public:
|
||||
operator CStr8() const;
|
||||
};
|
||||
|
||||
/*
|
||||
CEntityList
|
||||
|
||||
DESCRIPTION: Represents a group of entities that is the target/subject of
|
||||
a network command. Use for easy serialization of one or more entity IDs.
|
||||
|
||||
SERIALIZED FORMAT: The entities are stored as a sequence of 16-bit ints, the
|
||||
termination of the list marked by an integer with HANDLE_SENTINEL_BIT
|
||||
set. The length is thus 2*(number of entities)
|
||||
*/
|
||||
struct CEntityList: public std::vector<HEntity>
|
||||
{
|
||||
// Create an empty list
|
||||
inline CEntityList()
|
||||
{}
|
||||
// Create a list from an existing entity vector
|
||||
inline CEntityList(const std::vector<HEntity> &vect):
|
||||
std::vector<HEntity>(vect)
|
||||
{}
|
||||
// Create a list containing one entity
|
||||
inline CEntityList(HEntity oneEntity)
|
||||
{
|
||||
push_back(oneEntity);
|
||||
}
|
||||
|
||||
uint GetSerializedLength() const;
|
||||
u8 *Serialize(u8 *buffer) const;
|
||||
const u8 *Deserialize(const u8 *buffer, const u8 *end);
|
||||
operator CStr8() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -54,7 +54,7 @@ HEntity CEntityManager::create( CBaseEntity* base, CVector3D position, float ori
|
||||
{
|
||||
assert( base );
|
||||
if( !base )
|
||||
return( HEntity() );
|
||||
return HEntity();
|
||||
|
||||
while( m_entities[m_nextalloc].m_refcount )
|
||||
{
|
||||
|
@ -192,10 +192,12 @@ JSBool CProjectile::Construct( JSContext* cx, JSObject* obj, unsigned int argc,
|
||||
if( argc >= 7 )
|
||||
Miss = argv[6]; // Script to run on impact with the floor.
|
||||
|
||||
{
|
||||
CProjectile* p = g_ProjectileManager.AddProjectile( Model, Here, There, Speed / 1000.0f, Originator, Impact, Miss );
|
||||
|
||||
*rval = ToJSVal<CProjectile>( *p );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
fail:
|
||||
*rval = JSVAL_NULL;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "Vector3D.h"
|
||||
#include "Vector2D.h"
|
||||
#include "Singleton.h"
|
||||
#include "Scripting/ScriptableObject.h"
|
||||
#include "scripting/ScriptableObject.h"
|
||||
#include "scripting/DOMEvent.h"
|
||||
#include "ScriptObject.h"
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
#define SCHEDULER_INCLUDED
|
||||
|
||||
#include <queue>
|
||||
#include <list>
|
||||
|
||||
#include "EntityMessage.h"
|
||||
#include "EntityHandles.h"
|
||||
#include "Singleton.h"
|
||||
@ -73,7 +75,7 @@ struct CScheduler : public Singleton<CScheduler>
|
||||
|
||||
class CJSProgressTimer : public CJSObject<CJSProgressTimer>
|
||||
{
|
||||
friend CScheduler;
|
||||
friend struct CScheduler;
|
||||
double m_Max, m_Current, m_Increment;
|
||||
JSFunction* m_Callback;
|
||||
JSObject* m_OperateOn;
|
||||
|
@ -94,7 +94,7 @@ bool CScriptObject::Run( JSObject* Context, jsval* rval, uintN argc, jsval* argv
|
||||
bool CScriptObject::Run( JSObject* Context, uintN argc, jsval* argv )
|
||||
{
|
||||
jsval Temp;
|
||||
if( !Run( Context, &Temp ) )
|
||||
if( !Run( Context, &Temp, argc, argv ) )
|
||||
return( false );
|
||||
return( g_ScriptingHost.ValueToBool( Temp ) );
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <timer.h>
|
||||
#include "Profile.h"
|
||||
|
||||
@ -19,6 +21,8 @@
|
||||
|
||||
#include "gui/CGUI.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern CConsole *g_Console;
|
||||
|
||||
CSimulation::CSimulation(CGame *pGame):
|
||||
@ -119,20 +123,134 @@ void CSimulation::Simulate()
|
||||
PROFILE_END( "turn manager update" );
|
||||
}
|
||||
|
||||
// Location randomizer, for group orders...
|
||||
// Having the group turn up at the destination with /some/ sort of cohesion is
|
||||
// good but tasking them all to the exact same point will leave them brawling
|
||||
// for it at the other end (it shouldn't, but the PASAP pathfinder is too
|
||||
// simplistic)
|
||||
|
||||
// Task them all to a point within a radius of the target, radius depends upon
|
||||
// the number of units in the group.
|
||||
|
||||
void RandomizeLocations(CEntityOrder order, const vector <HEntity> &entities, bool clearQueue)
|
||||
{
|
||||
vector<HEntity>::const_iterator it;
|
||||
float radius = 2.0f * sqrt( (float)entities.size() - 1 );
|
||||
|
||||
for (it = entities.begin(); it < entities.end(); it++)
|
||||
{
|
||||
float _x, _y;
|
||||
CEntityOrder randomizedOrder = order;
|
||||
|
||||
do
|
||||
{
|
||||
_x = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
|
||||
_y = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
|
||||
}
|
||||
while( ( _x * _x ) + ( _y * _y ) > 1.0f );
|
||||
|
||||
randomizedOrder.m_data[0].location.x += _x * radius;
|
||||
randomizedOrder.m_data[0].location.y += _y * radius;
|
||||
|
||||
// Clamp it to within the map, just in case.
|
||||
float mapsize = (float)g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide() * CELL_SIZE;
|
||||
|
||||
if( randomizedOrder.m_data[0].location.x < 0.0f )
|
||||
randomizedOrder.m_data[0].location.x = 0.0f;
|
||||
if( randomizedOrder.m_data[0].location.x >= mapsize )
|
||||
randomizedOrder.m_data[0].location.x = mapsize;
|
||||
if( randomizedOrder.m_data[0].location.y < 0.0f )
|
||||
randomizedOrder.m_data[0].location.y = 0.0f;
|
||||
if( randomizedOrder.m_data[0].location.y >= mapsize )
|
||||
randomizedOrder.m_data[0].location.y = mapsize;
|
||||
|
||||
if( clearQueue )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( randomizedOrder );
|
||||
}
|
||||
}
|
||||
|
||||
void QueueOrder(CEntityOrder order, const vector <HEntity> &entities, bool clearQueue)
|
||||
{
|
||||
vector<HEntity>::const_iterator it;
|
||||
|
||||
for (it = entities.begin(); it < entities.end(); it++)
|
||||
{
|
||||
if( clearQueue )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( order );
|
||||
}
|
||||
}
|
||||
|
||||
uint CSimulation::TranslateMessage(CNetMessage *pMsg, uint clientMask, void *userdata)
|
||||
{
|
||||
CSimulation *pSimulation=(CSimulation *)userdata;
|
||||
CEntityOrder order;
|
||||
bool clearQueue = true;
|
||||
|
||||
#define ENTITY_POSITION(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].location.x=(float)msg->m_TargetX; \
|
||||
order.m_data[0].location.y=(float)msg->m_TargetY; \
|
||||
RandomizeLocations(order, msg->m_Entities, clearQueue); \
|
||||
} while(0)
|
||||
#define ENTITY_ENTITY(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].entity=msg->m_Target; \
|
||||
QueueOrder(order, msg->m_Entities, clearQueue); \
|
||||
} while(0)
|
||||
|
||||
CEntityOrder entOrder;
|
||||
switch (pMsg->GetType())
|
||||
{
|
||||
case NMT_GotoCommand:
|
||||
CGotoCommand *msg=(CGotoCommand *)pMsg;
|
||||
entOrder.m_type=CEntityOrder::ORDER_GOTO;
|
||||
entOrder.m_data[0].location.x=(float)msg->m_TargetX;
|
||||
entOrder.m_data[0].location.y=(float)msg->m_TargetY;
|
||||
CEntity *ent=msg->m_Entity;
|
||||
ent->pushOrder( entOrder );
|
||||
case NMT_AddWaypoint:
|
||||
{
|
||||
CAddWaypoint *msg=(CAddWaypoint *)pMsg;
|
||||
order.m_type=CEntityOrder::ORDER_LAST;
|
||||
order.m_data[0].location.x=(float)msg->m_TargetX;
|
||||
order.m_data[0].location.y=(float)msg->m_TargetY;
|
||||
vector<HEntity>::iterator it = msg->m_Entities.begin();
|
||||
for (;it != msg->m_Entities.end(); ++it)
|
||||
{
|
||||
deque<CEntityOrder>::const_iterator ord_it;
|
||||
ord_it=(*it)->m_orderQueue.end() - 1;
|
||||
for (;ord_it >= (*it)->m_orderQueue.begin();--ord_it)
|
||||
{
|
||||
if (ord_it->m_type == CEntityOrder::ORDER_PATH_END_MARKER)
|
||||
{
|
||||
order.m_type = CEntityOrder::ORDER_GOTO;
|
||||
(*it)->pushOrder(order);
|
||||
break;
|
||||
}
|
||||
if (ord_it->m_type == CEntityOrder::ORDER_PATROL)
|
||||
{
|
||||
order.m_type = ord_it->m_type;
|
||||
(*it)->pushOrder(order);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (order.m_type == CEntityOrder::ORDER_LAST)
|
||||
{
|
||||
LOG(ERROR, "simulation", "Got an AddWaypoint message for an entity that isn't moving.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NMT_Goto:
|
||||
ENTITY_POSITION(CGoto, ORDER_GOTO);
|
||||
break;
|
||||
case NMT_Patrol:
|
||||
ENTITY_POSITION(CPatrol, ORDER_PATROL);
|
||||
break;
|
||||
case NMT_AttackMelee:
|
||||
ENTITY_ENTITY(CAttackMelee, ORDER_ATTACK_MELEE);
|
||||
break;
|
||||
case NMT_Gather:
|
||||
ENTITY_ENTITY(CGather, ORDER_GATHER);
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user