diff options
Diffstat (limited to 'src/game')
167 files changed, 14596 insertions, 14075 deletions
diff --git a/src/game/client/animstate.cpp b/src/game/client/animstate.cpp index d8c20dec..cb706774 100644 --- a/src/game/client/animstate.cpp +++ b/src/game/client/animstate.cpp @@ -1,95 +1,94 @@ -#include <base/math.hpp> -#include <engine/e_client_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <base/math.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include "animstate.hpp" +#include "animstate.h" -static void anim_seq_eval(ANIM_SEQUENCE *seq, float time, ANIM_KEYFRAME *frame) +static void AnimSeqEval(ANIM_SEQUENCE *pSeq, float Time, ANIM_KEYFRAME *pFrame) { - if(seq->num_frames == 0) + if(pSeq->m_NumFrames == 0) { - frame->time = 0; - frame->x = 0; - frame->y = 0; - frame->angle = 0; + pFrame->m_Time = 0; + pFrame->m_X = 0; + pFrame->m_Y = 0; + pFrame->m_Angle = 0; } - else if(seq->num_frames == 1) + else if(pSeq->m_NumFrames == 1) { - *frame = seq->frames[0]; + *pFrame = pSeq->m_aFrames[0]; } else { //time = max(0.0f, min(1.0f, time / duration)); // TODO: use clamp - ANIM_KEYFRAME *frame1 = 0; - ANIM_KEYFRAME *frame2 = 0; - float blend = 0.0f; + ANIM_KEYFRAME *pFrame1 = 0; + ANIM_KEYFRAME *pFrame2 = 0; + float Blend = 0.0f; // TODO: make this smarter.. binary search - for (int i = 1; i < seq->num_frames; i++) + for (int i = 1; i < pSeq->m_NumFrames; i++) { - if (seq->frames[i-1].time <= time && seq->frames[i].time >= time) + if (pSeq->m_aFrames[i-1].m_Time <= Time && pSeq->m_aFrames[i].m_Time >= Time) { - frame1 = &seq->frames[i-1]; - frame2 = &seq->frames[i]; - blend = (time - frame1->time) / (frame2->time - frame1->time); + pFrame1 = &pSeq->m_aFrames[i-1]; + pFrame2 = &pSeq->m_aFrames[i]; + Blend = (Time - pFrame1->m_Time) / (pFrame2->m_Time - pFrame1->m_Time); break; } } - if (frame1 && frame2) + if (pFrame1 && pFrame2) { - frame->time = time; - frame->x = mix(frame1->x, frame2->x, blend); - frame->y = mix(frame1->y, frame2->y, blend); - frame->angle = mix(frame1->angle, frame2->angle, blend); + pFrame->m_Time = Time; + pFrame->m_X = mix(pFrame1->m_X, pFrame2->m_X, Blend); + pFrame->m_Y = mix(pFrame1->m_Y, pFrame2->m_Y, Blend); + pFrame->m_Angle = mix(pFrame1->m_Angle, pFrame2->m_Angle, Blend); } } } -static void anim_add_keyframe(ANIM_KEYFRAME *seq, ANIM_KEYFRAME *added, float amount) +static void AnimAddKeyframe(ANIM_KEYFRAME *pSeq, ANIM_KEYFRAME *pAdded, float Amount) { - seq->x += added->x*amount; - seq->y += added->y*amount; - seq->angle += added->angle*amount; + pSeq->m_X += pAdded->m_X*Amount; + pSeq->m_Y += pAdded->m_Y*Amount; + pSeq->m_Angle += pAdded->m_Angle*Amount; } -static void anim_add(ANIMSTATE *state, ANIMSTATE *added, float amount) +static void AnimAdd(CAnimState *pState, CAnimState *pAdded, float Amount) { - anim_add_keyframe(&state->body, &added->body, amount); - anim_add_keyframe(&state->back_foot, &added->back_foot, amount); - anim_add_keyframe(&state->front_foot, &added->front_foot, amount); - anim_add_keyframe(&state->attach, &added->attach, amount); + AnimAddKeyframe(pState->GetBody(), pAdded->GetBody(), Amount); + AnimAddKeyframe(pState->GetBackFoot(), pAdded->GetBackFoot(), Amount); + AnimAddKeyframe(pState->GetFrontFoot(), pAdded->GetFrontFoot(), Amount); + AnimAddKeyframe(pState->GetAttach(), pAdded->GetAttach(), Amount); } -void ANIMSTATE::set(ANIMATION *anim, float time) +void CAnimState::Set(ANIMATION *pAnim, float Time) { - anim_seq_eval(&anim->body, time, &body); - anim_seq_eval(&anim->back_foot, time, &back_foot); - anim_seq_eval(&anim->front_foot, time, &front_foot); - anim_seq_eval(&anim->attach, time, &attach); + AnimSeqEval(&pAnim->m_Body, Time, &m_Body); + AnimSeqEval(&pAnim->m_BackFoot, Time, &m_BackFoot); + AnimSeqEval(&pAnim->m_FrontFoot, Time, &m_FrontFoot); + AnimSeqEval(&pAnim->m_Attach, Time, &m_Attach); } -void ANIMSTATE::add(ANIMATION *anim, float time, float amount) +void CAnimState::Add(ANIMATION *pAnim, float Time, float Amount) { - ANIMSTATE add; - add.set(anim, time); - anim_add(this, &add, amount); + CAnimState Add; + Add.Set(pAnim, Time); + AnimAdd(this, &Add, Amount); } -ANIMSTATE *ANIMSTATE::get_idle() +CAnimState *CAnimState::GetIdle() { - static ANIMSTATE state; - static bool init = true; + static CAnimState State; + static bool Init = true; - if(init) + if(Init) { - state.set(&data->animations[ANIM_BASE], 0); - state.add(&data->animations[ANIM_IDLE], 0, 1.0f); - init = false; + State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0); + State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); + Init = false; } - return &state; + return &State; } diff --git a/src/game/client/animstate.h b/src/game/client/animstate.h new file mode 100644 index 00000000..e7fce9a1 --- /dev/null +++ b/src/game/client/animstate.h @@ -0,0 +1,22 @@ +#ifndef GAME_CLIENT_ANIMSTATE_H +#define GAME_CLIENT_ANIMSTATE_H + +class CAnimState +{ + ANIM_KEYFRAME m_Body; + ANIM_KEYFRAME m_BackFoot; + ANIM_KEYFRAME m_FrontFoot; + ANIM_KEYFRAME m_Attach; + +public: + ANIM_KEYFRAME *GetBody() { return &m_Body; }; + ANIM_KEYFRAME *GetBackFoot() { return &m_BackFoot; }; + ANIM_KEYFRAME *GetFrontFoot() { return &m_FrontFoot; }; + ANIM_KEYFRAME *GetAttach() { return &m_Attach; }; + void Set(ANIMATION *pAnim, float Time); + void Add(ANIMATION *pAdded, float Time, float Amount); + + static CAnimState *GetIdle(); +}; + +#endif diff --git a/src/game/client/animstate.hpp b/src/game/client/animstate.hpp deleted file mode 100644 index 4b84dd66..00000000 --- a/src/game/client/animstate.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef GAME_CLIENT_ANIMATION_H -#define GAME_CLIENT_ANIMATION_H - -class ANIMSTATE -{ -public: - ANIM_KEYFRAME body; - ANIM_KEYFRAME back_foot; - ANIM_KEYFRAME front_foot; - ANIM_KEYFRAME attach; - - void set(ANIMATION *anim, float time); - void add(ANIMATION *added, float time, float amount); - - static ANIMSTATE *get_idle(); -}; - -//void anim_seq_eval(ANIM_SEQUENCE *seq, float time, ANIM_KEYFRAME *frame); -//void anim_eval(ANIMATION *anim, float time, ANIM_STATE *state); -//void anim_add_keyframe(ANIM_KEYFRAME *seq, ANIM_KEYFRAME *added, float amount); -//void anim_add(ANIM_STATE *state, ANIM_STATE *added, float amount); -//void anim_eval_add(ANIM_STATE *state, ANIMATION *anim, float time, float amount); - -#endif diff --git a/src/game/client/clienthooks.cpp b/src/game/client/clienthooks.cpp deleted file mode 100644 index 76fa8dcd..00000000 --- a/src/game/client/clienthooks.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include <string.h> -#include <engine/e_client_interface.h> -#include <game/version.hpp> - -#include "gameclient.hpp" -#include "components/console.hpp" - - - -// clean hooks -void modc_entergame() {} -void modc_shutdown() {} -void modc_console_init() { gameclient.on_console_init(); } -void modc_save_config() { gameclient.on_save(); } -void modc_init() { gameclient.on_init(); } -void modc_connected() { gameclient.on_connected(); } -void modc_predict() { gameclient.on_predict(); } -void modc_newsnapshot() { gameclient.on_snapshot(); } -int modc_snap_input(int *data) { return gameclient.on_snapinput(data); } -void modc_statechange(int state, int old) { gameclient.on_statechange(state, old); } -void modc_render() { gameclient.on_render(); } -void modc_message(int msgtype) { gameclient.on_message(msgtype); } -void modc_rcon_line(const char *line) { gameclient.console->print_line(1, line); } - -const char *modc_net_version() { return GAME_NETVERSION; } -const char *modc_getitemname(int type) { return netobj_get_name(type); } - diff --git a/src/game/client/component.h b/src/game/client/component.h new file mode 100644 index 00000000..410be623 --- /dev/null +++ b/src/game/client/component.h @@ -0,0 +1,43 @@ +#ifndef GAME_CLIENT_COMPONENT_H +#define GAME_CLIENT_COMPONENT_H + +#include <engine/input.h> +#include "gameclient.h" + +class CComponent +{ +protected: + friend class CGameClient; + + CGameClient *m_pClient; + + // perhaps propagte pointers for these as well + class IKernel *Kernel() const { return m_pClient->Kernel(); } + class IGraphics *Graphics() const { return m_pClient->Graphics(); } + class ITextRender *TextRender() const { return m_pClient->TextRender(); } + class IClient *Client() const { return m_pClient->Client(); } + class IInput *Input() const { return m_pClient->Input(); } + class IStorage *Storage() const { return m_pClient->Storage(); } + class CUI *UI() const { return m_pClient->UI(); } + class ISound *Sound() const { return m_pClient->Sound(); } + class CRenderTools *RenderTools() const { return m_pClient->RenderTools(); } + class IConsole *Console() const { return m_pClient->Console(); } + class IDemoPlayer *DemoPlayer() const { return m_pClient->DemoPlayer(); } + class IServerBrowser *ServerBrowser() const { return m_pClient->ServerBrowser(); } + class CLayers *Layers() const { return m_pClient->Layers(); } + class CCollision *Collision() const { return m_pClient->Collision(); } +public: + virtual ~CComponent() {} + + virtual void OnStateChange(int NewState, int OldState) {}; + virtual void OnConsoleInit() {}; + virtual void OnInit() {}; + virtual void OnReset() {}; + virtual void OnRender() {}; + virtual void OnMapLoad() {}; + virtual void OnMessage(int Msg, void *pRawMsg) {} + virtual bool OnMouseMove(float x, float y) { return false; } + virtual bool OnInput(IInput::CEvent e) { return false; } +}; + +#endif diff --git a/src/game/client/component.hpp b/src/game/client/component.hpp deleted file mode 100644 index 6534e56b..00000000 --- a/src/game/client/component.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GAME_CLIENT_GAMESYSTEM_H -#define GAME_CLIENT_GAMESYSTEM_H - -#include <engine/e_client_interface.h> -#include "gameclient.hpp" - -class GAMECLIENT; - -class COMPONENT -{ -protected: - friend class GAMECLIENT; - - GAMECLIENT *client; - - // perhaps propagte pointers for these as well - class IGraphics *Graphics() const { return client->Graphics(); } - class CUI *UI() const { return client->UI(); } - class CRenderTools *RenderTools() const { return client->RenderTools(); } -public: - virtual ~COMPONENT() {} - - virtual void on_statechange(int new_state, int old_state) {}; - virtual void on_console_init() {}; - virtual void on_init() {}; - virtual void on_save() {}; - virtual void on_reset() {}; - virtual void on_render() {}; - virtual void on_mapload() {}; - virtual void on_message(int msg, void *rawmsg) {} - virtual bool on_mousemove(float x, float y) { return false; } - virtual bool on_input(INPUT_EVENT e) { return false; } -}; - -#endif diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index e4252656..533658f2 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -1,184 +1,188 @@ -#include <stdlib.h> // atoi -#include <string.h> // strcmp -#include <engine/e_client_interface.h> -#include "binds.hpp" +#include <engine/config.h> +#include <engine/shared/config.h> +#include "binds.h" -bool BINDS::BINDS_SPECIAL::on_input(INPUT_EVENT e) +bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event) { // don't handle invalid events and keys that arn't set to anything - if(e.key >= KEY_F1 && e.key <= KEY_F15 && binds->keybindings[e.key][0] != 0) + if(Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F15 && m_pBinds->m_aaKeyBindings[Event.m_Key][0] != 0) { - int stroke = 0; - if(e.flags&INPFLAG_PRESS) - stroke = 1; - console_execute_line_stroked(stroke, binds->keybindings[e.key]); + int Stroke = 0; + if(Event.m_Flags&IInput::FLAG_PRESS) + Stroke = 1; + + m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaKeyBindings[Event.m_Key]); return true; } return false; } -BINDS::BINDS() +CBinds::CBinds() { - mem_zero(keybindings, sizeof(keybindings)); - special_binds.binds = this; + mem_zero(m_aaKeyBindings, sizeof(m_aaKeyBindings)); + m_SpecialBinds.m_pBinds = this; } -void BINDS::bind(int keyid, const char *str) +void CBinds::Bind(int KeyId, const char *pStr) { - if(keyid < 0 || keyid >= KEY_LAST) + if(KeyId < 0 || KeyId >= KEY_LAST) return; - str_copy(keybindings[keyid], str, sizeof(keybindings[keyid])); - if(!keybindings[keyid][0]) - dbg_msg("binds", "unbound %s (%d)", inp_key_name(keyid), keyid); + str_copy(m_aaKeyBindings[KeyId], pStr, sizeof(m_aaKeyBindings[KeyId])); + if(!m_aaKeyBindings[KeyId][0]) + dbg_msg("binds", "unbound %s (%d)", Input()->KeyName(KeyId), KeyId); else - dbg_msg("binds", "bound %s (%d) = %s", inp_key_name(keyid), keyid, keybindings[keyid]); + dbg_msg("binds", "bound %s (%d) = %s", Input()->KeyName(KeyId), KeyId, m_aaKeyBindings[KeyId]); } -bool BINDS::on_input(INPUT_EVENT e) +bool CBinds::OnInput(IInput::CEvent e) { // don't handle invalid events and keys that arn't set to anything - if(e.key <= 0 || e.key >= KEY_LAST || keybindings[e.key][0] == 0) + if(e.m_Key <= 0 || e.m_Key >= KEY_LAST || m_aaKeyBindings[e.m_Key][0] == 0) return false; - int stroke = 0; - if(e.flags&INPFLAG_PRESS) - stroke = 1; - console_execute_line_stroked(stroke, keybindings[e.key]); + int Stroke = 0; + if(e.m_Flags&IInput::FLAG_PRESS) + Stroke = 1; + Console()->ExecuteLineStroked(Stroke, m_aaKeyBindings[e.m_Key]); return true; } -void BINDS::unbindall() +void CBinds::UnbindAll() { for(int i = 0; i < KEY_LAST; i++) - keybindings[i][0] = 0; + m_aaKeyBindings[i][0] = 0; } -const char *BINDS::get(int keyid) +const char *CBinds::Get(int KeyId) { - if(keyid > 0 && keyid < KEY_LAST) - return keybindings[keyid]; + if(KeyId > 0 && KeyId < KEY_LAST) + return m_aaKeyBindings[KeyId]; return ""; } -const char *BINDS::get_key(const char *bindstr) +const char *CBinds::GetKey(const char *pBindStr) { - for(int keyid = 0; keyid < KEY_LAST; keyid++) + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) { - const char *bind = get(keyid); - if(!bind[0]) + const char *pBind = Get(KeyId); + if(!pBind[0]) continue; - if(strcmp(bind, bindstr) == 0) - return inp_key_name(keyid); + if(str_comp(pBind, pBindStr) == 0) + return Input()->KeyName(KeyId); } return ""; } -void BINDS::set_defaults() +void CBinds::SetDefaults() { // set default key bindings - unbindall(); - bind(KEY_F1, "toggle_local_console"); - bind(KEY_F2, "toggle_remote_console"); - bind(KEY_TAB, "+scoreboard"); - bind(KEY_F10, "screenshot"); - - bind('a', "+left"); - bind('d', "+right"); - - bind(KEY_SPACE, "+jump"); - bind(KEY_MOUSE_1, "+fire"); - bind(KEY_MOUSE_2, "+hook"); - bind(KEY_LSHIFT, "+emote"); - - bind('1', "+weapon1"); - bind('2', "+weapon2"); - bind('3', "+weapon3"); - bind('4', "+weapon4"); - bind('5', "+weapon5"); + UnbindAll(); + Bind(KEY_F1, "toggle_local_console"); + Bind(KEY_F2, "toggle_remote_console"); + Bind(KEY_TAB, "+scoreboard"); + Bind(KEY_F10, "screenshot"); + + Bind('a', "+left"); + Bind('d', "+right"); + + Bind(KEY_SPACE, "+jump"); + Bind(KEY_MOUSE_1, "+fire"); + Bind(KEY_MOUSE_2, "+hook"); + Bind(KEY_LSHIFT, "+emote"); + + Bind('1', "+weapon1"); + Bind('2', "+weapon2"); + Bind('3', "+weapon3"); + Bind('4', "+weapon4"); + Bind('5', "+weapon5"); - bind(KEY_MOUSE_WHEEL_UP, "+prevweapon"); - bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon"); + Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon"); + Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon"); - bind('t', "chat all"); - bind('y', "chat team"); + Bind('t', "chat all"); + Bind('y', "chat team"); - bind(KEY_F3, "vote yes"); - bind(KEY_F4, "vote no"); + Bind(KEY_F3, "vote yes"); + Bind(KEY_F4, "vote no"); } -void BINDS::on_console_init() +void CBinds::OnConsoleInit() { // bindings - MACRO_REGISTER_COMMAND("bind", "sr", CFGFLAG_CLIENT, con_bind, this, "Bind key to execute the command"); - MACRO_REGISTER_COMMAND("unbind", "s", CFGFLAG_CLIENT, con_unbind, this, "Unbind key"); - MACRO_REGISTER_COMMAND("unbindall", "", CFGFLAG_CLIENT, con_unbindall, this, "Unbind all keys"); - MACRO_REGISTER_COMMAND("dump_binds", "", CFGFLAG_CLIENT, con_dump_binds, this, "Dump binds"); + IConfig *pConfig = Kernel()->RequestInterface<IConfig>(); + if(pConfig) + pConfig->RegisterCallback(ConfigSaveCallback, this); + + Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); + Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); + Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); + Console()->Register("dump_binds", "", CFGFLAG_CLIENT, ConDumpBinds, this, "Dump binds"); // default bindings - set_defaults(); + SetDefaults(); } -void BINDS::con_bind(void *result, void *user_data) +void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData) { - BINDS *binds = (BINDS *)user_data; - const char *key_name = console_arg_string(result, 0); - int id = binds->get_key_id(key_name); + CBinds *pBinds = (CBinds *)pUserData; + const char *pKeyName = pResult->GetString(0); + int id = pBinds->GetKeyId(pKeyName); if(!id) { - dbg_msg("binds", "key %s not found", key_name); + dbg_msg("binds", "key %s not found", pKeyName); return; } - binds->bind(id, console_arg_string(result, 1)); + pBinds->Bind(id, pResult->GetString(1)); } -void BINDS::con_unbind(void *result, void *user_data) +void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData) { - BINDS *binds = (BINDS *)user_data; - const char *key_name = console_arg_string(result, 0); - int id = binds->get_key_id(key_name); + CBinds *pBinds = (CBinds *)pUserData; + const char *pKeyName = pResult->GetString(0); + int id = pBinds->GetKeyId(pKeyName); if(!id) { - dbg_msg("binds", "key %s not found", key_name); + dbg_msg("binds", "key %s not found", pKeyName); return; } - binds->bind(id, ""); + pBinds->Bind(id, ""); } -void BINDS::con_unbindall(void *result, void *user_data) +void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData) { - BINDS *binds = (BINDS *)user_data; - binds->unbindall(); + CBinds *pBinds = (CBinds *)pUserData; + pBinds->UnbindAll(); } -void BINDS::con_dump_binds(void *result, void *user_data) +void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData) { - BINDS *binds = (BINDS *)user_data; + CBinds *pBinds = (CBinds *)pUserData; for(int i = 0; i < KEY_LAST; i++) { - if(binds->keybindings[i][0] == 0) + if(pBinds->m_aaKeyBindings[i][0] == 0) continue; - dbg_msg("binds", "%s (%d) = %s", inp_key_name(i), i, binds->keybindings[i]); + dbg_msg("binds", "%s (%d) = %s", pBinds->Input()->KeyName(i), i, pBinds->m_aaKeyBindings[i]); } } -int BINDS::get_key_id(const char *key_name) +int CBinds::GetKeyId(const char *pKeyName) { // check for numeric - if(key_name[0] == '&') + if(pKeyName[0] == '&') { - int i = atoi(key_name+1); + int i = str_toint(pKeyName+1); if(i > 0 && i < KEY_LAST) return i; // numeric } @@ -186,37 +190,39 @@ int BINDS::get_key_id(const char *key_name) // search for key for(int i = 0; i < KEY_LAST; i++) { - if(strcmp(key_name, inp_key_name(i)) == 0) + if(str_comp(pKeyName, Input()->KeyName(i)) == 0) return i; } return 0; } -void BINDS::on_save() +void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) { - char buffer[256]; - char *end = buffer+sizeof(buffer)-8; - client_save_line("unbindall"); + CBinds *pSelf = (CBinds *)pUserData; + + char aBuffer[256]; + char *pEnd = aBuffer+sizeof(aBuffer)-8; + pConfig->WriteLine("unbindall"); for(int i = 0; i < KEY_LAST; i++) { - if(keybindings[i][0] == 0) + if(pSelf->m_aaKeyBindings[i][0] == 0) continue; - str_format(buffer, sizeof(buffer), "bind %s ", inp_key_name(i)); + str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i)); // process the string. we need to escape some characters - const char *src = keybindings[i]; - char *dst = buffer + strlen(buffer); - *dst++ = '"'; - while(*src && dst < end) + const char *pSrc = pSelf->m_aaKeyBindings[i]; + char *pDst = aBuffer + str_length(aBuffer); + *pDst++ = '"'; + while(*pSrc && pDst < pEnd) { - if(*src == '"' || *src == '\\') // escape \ and " - *dst++ = '\\'; - *dst++ = *src++; + if(*pSrc == '"' || *pSrc == '\\') // escape \ and " + *pDst++ = '\\'; + *pDst++ = *pSrc++; } - *dst++ = '"'; - *dst++ = 0; + *pDst++ = '"'; + *pDst++ = 0; - client_save_line(buffer); + pConfig->WriteLine(aBuffer); } } diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h new file mode 100644 index 00000000..e8393979 --- /dev/null +++ b/src/game/client/components/binds.h @@ -0,0 +1,41 @@ +#ifndef GAME_CLIENT_COMPONENTS_BINDS_H +#define GAME_CLIENT_COMPONENTS_BINDS_H +#include <game/client/component.h> +#include <engine/keys.h> + +class CBinds : public CComponent +{ + char m_aaKeyBindings[KEY_LAST][128]; + + int GetKeyId(const char *pKeyName); + + static void ConBind(IConsole::IResult *pResult, void *pUserData); + static void ConUnbind(IConsole::IResult *pResult, void *pUserData); + static void ConUnbindAll(IConsole::IResult *pResult, void *pUserData); + static void ConDumpBinds(IConsole::IResult *pResult, void *pUserData); + class IConsole *GetConsole() const { return Console(); } + + static void ConfigSaveCallback(class IConfig *pConfig, void *pUserData); + +public: + CBinds(); + + class CBindsSpecial : public CComponent + { + public: + CBinds *m_pBinds; + virtual bool OnInput(IInput::CEvent Event); + }; + + CBindsSpecial m_SpecialBinds; + + void Bind(int KeyId, const char *pStr); + void SetDefaults(); + void UnbindAll(); + const char *Get(int KeyId); + const char *GetKey(const char *pBindStr); + + virtual void OnConsoleInit(); + virtual bool OnInput(IInput::CEvent Event); +}; +#endif diff --git a/src/game/client/components/binds.hpp b/src/game/client/components/binds.hpp deleted file mode 100644 index bdf242f9..00000000 --- a/src/game/client/components/binds.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#include <game/client/component.hpp> - -class BINDS : public COMPONENT -{ - char keybindings[KEY_LAST][128]; - - int get_key_id(const char *key_name); - - static void con_bind(void *result, void *user_data); - static void con_unbind(void *result, void *user_data); - static void con_unbindall(void *result, void *user_data); - static void con_dump_binds(void *result, void *user_data); - -public: - BINDS(); - - class BINDS_SPECIAL : public COMPONENT - { - public: - BINDS *binds; - virtual bool on_input(INPUT_EVENT e); - }; - - BINDS_SPECIAL special_binds; - - void bind(int keyid, const char *str); - void set_defaults(); - void unbindall(); - const char *get(int keyid); - const char *get_key(const char *bindstr); - - virtual void on_save(); - virtual void on_console_init(); - virtual bool on_input(INPUT_EVENT e); -}; diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index b86ed658..c3eb3b56 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -1,36 +1,36 @@ -#include <engine/e_client_interface.h> -#include <engine/e_config.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/gameclient.hpp> +#include <game/client/gameclient.h> -#include "broadcast.hpp" +#include "broadcast.h" -void BROADCAST::on_reset() +void CBroadcast::OnReset() { - broadcast_time = 0; + m_BroadcastTime = 0; } -void BROADCAST::on_render() +void CBroadcast::OnRender() { Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); - if(time_get() < broadcast_time) + if(time_get() < m_BroadcastTime) { - float w = gfx_text_width(0, 14, broadcast_text, -1); - gfx_text(0, 150*Graphics()->ScreenAspect()-w/2, 35, 14, broadcast_text, -1); + float w = TextRender()->TextWidth(0, 14, m_aBroadcastText, -1); + TextRender()->Text(0, 150*Graphics()->ScreenAspect()-w/2, 35, 14, m_aBroadcastText, -1); } } -void BROADCAST::on_message(int msgtype, void *rawmsg) +void CBroadcast::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_BROADCAST) + if(MsgType == NETMSGTYPE_SV_BROADCAST) { - NETMSG_SV_BROADCAST *msg = (NETMSG_SV_BROADCAST *)rawmsg; - str_copy(broadcast_text, msg->message, sizeof(broadcast_text)); - broadcast_time = time_get()+time_freq()*10; + CNetMsg_Sv_Broadcast *pMsg = (CNetMsg_Sv_Broadcast *)pRawMsg; + str_copy(m_aBroadcastText, pMsg->m_pMessage, sizeof(m_aBroadcastText)); + m_BroadcastTime = time_get()+time_freq()*10; } } diff --git a/src/game/client/components/broadcast.h b/src/game/client/components/broadcast.h new file mode 100644 index 00000000..ed281a2f --- /dev/null +++ b/src/game/client/components/broadcast.h @@ -0,0 +1,17 @@ +#ifndef GAME_CLIENT_COMPONENTS_BROADCAST_H +#define GAME_CLIENT_COMPONENTS_BROADCAST_H +#include <game/client/component.h> + +class CBroadcast : public CComponent +{ +public: + // broadcasts + char m_aBroadcastText[1024]; + int64 m_BroadcastTime; + + virtual void OnReset(); + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); +}; + +#endif diff --git a/src/game/client/components/broadcast.hpp b/src/game/client/components/broadcast.hpp deleted file mode 100644 index 102201cc..00000000 --- a/src/game/client/components/broadcast.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <game/client/component.hpp> - -class BROADCAST : public COMPONENT -{ -public: - // broadcasts - char broadcast_text[1024]; - int64 broadcast_time; - - virtual void on_reset(); - virtual void on_render(); - virtual void on_message(int msgtype, void *rawmsg); -}; - diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp index 7b188e00..96baf459 100644 --- a/src/game/client/components/camera.cpp +++ b/src/game/client/components/camera.cpp @@ -1,40 +1,37 @@ -extern "C" { - #include <engine/e_config.h> - #include <engine/e_client_interface.h> -} +#include <engine/shared/config.h> -#include <base/math.hpp> -#include <game/collision.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/component.hpp> +#include <base/math.h> +#include <game/collision.h> +#include <game/client/gameclient.h> +#include <game/client/component.h> -#include "camera.hpp" -#include "controls.hpp" +#include "camera.h" +#include "controls.h" -CAMERA::CAMERA() +CCamera::CCamera() { } -void CAMERA::on_render() +void CCamera::OnRender() { //vec2 center; - zoom = 1.0f; + m_Zoom = 1.0f; // update camera center - if(gameclient.snap.spectate) - center = gameclient.controls->mouse_pos; + if(m_pClient->m_Snap.m_Spectate) + m_Center = m_pClient->m_pControls->m_MousePos; else { - float l = length(gameclient.controls->mouse_pos); - float deadzone = config.cl_mouse_deadzone; - float follow_factor = config.cl_mouse_followfactor/100.0f; - vec2 camera_offset(0, 0); + float l = length(m_pClient->m_pControls->m_MousePos); + float DeadZone = g_Config.m_ClMouseDeadzone; + float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; + vec2 CameraOffset(0, 0); - float offset_amount = max(l-deadzone, 0.0f) * follow_factor; + float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor; if(l > 0.0001f) // make sure that this isn't 0 - camera_offset = normalize(gameclient.controls->mouse_pos)*offset_amount; + CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount; - center = gameclient.local_character_pos + camera_offset; + m_Center = m_pClient->m_LocalCharacterPos + CameraOffset; } } diff --git a/src/game/client/components/camera.h b/src/game/client/components/camera.h new file mode 100644 index 00000000..9654bdf6 --- /dev/null +++ b/src/game/client/components/camera.h @@ -0,0 +1,16 @@ +#ifndef GAME_CLIENT_COMPONENTS_CAMERA_H +#define GAME_CLIENT_COMPONENTS_CAMERA_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CCamera : public CComponent +{ +public: + vec2 m_Center; + float m_Zoom; + + CCamera(); + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/camera.hpp b/src/game/client/components/camera.hpp deleted file mode 100644 index 1cb05f5b..00000000 --- a/src/game/client/components/camera.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class CAMERA : public COMPONENT -{ -public: - vec2 center; - float zoom; - - CAMERA(); - virtual void on_render(); -}; - diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index fdf1d21b..1a2c828d 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1,227 +1,263 @@ -#include <string.h> // strcmp -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/keys.h> +#include <engine/shared/config.h> -#include <game/client/gameclient.hpp> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/components/sounds.hpp> +#include <game/client/gameclient.h> -#include "chat.hpp" +#include <game/client/components/sounds.h> +#include <game/localization.h> -void CHAT::on_statechange(int new_state, int old_state) +#include "chat.h" + + +CChat::CChat() { - if(old_state <= CLIENTSTATE_CONNECTING) + OnReset(); +} + +void CChat::OnReset() +{ + for(int i = 0; i < MAX_LINES; i++) { - mode = MODE_NONE; + m_aLines[i].m_Time = 0; + m_aLines[i].m_aText[0] = 0; + m_aLines[i].m_aName[0] = 0; + } +} + +void CChat::OnStateChange(int NewState, int OldState) +{ + if(OldState <= IClient::STATE_CONNECTING) + { + m_Mode = MODE_NONE; for(int i = 0; i < MAX_LINES; i++) - lines[i].time = 0; - current_line = 0; + m_aLines[i].m_Time = 0; + m_CurrentLine = 0; } } -void CHAT::con_say(void *result, void *user_data) +void CChat::ConSay(IConsole::IResult *pResult, void *pUserData) { - ((CHAT*)user_data)->say(0, console_arg_string(result, 0)); + ((CChat*)pUserData)->Say(0, pResult->GetString(0)); } -void CHAT::con_sayteam(void *result, void *user_data) +void CChat::ConSayTeam(IConsole::IResult *pResult, void *pUserData) { - ((CHAT*)user_data)->say(1, console_arg_string(result, 0)); + ((CChat*)pUserData)->Say(1, pResult->GetString(0)); } -void CHAT::con_chat(void *result, void *user_data) +void CChat::ConChat(IConsole::IResult *pResult, void *pUserData) { - const char *mode = console_arg_string(result, 0); - if(strcmp(mode, "all") == 0) - ((CHAT*)user_data)->enable_mode(0); - else if(strcmp(mode, "team") == 0) - ((CHAT*)user_data)->enable_mode(1); + const char *pMode = pResult->GetString(0); + if(str_comp(pMode, "all") == 0) + ((CChat*)pUserData)->EnableMode(0); + else if(str_comp(pMode, "team") == 0) + ((CChat*)pUserData)->EnableMode(1); else dbg_msg("console", "expected all or team as mode"); } -void CHAT::on_console_init() +void CChat::OnConsoleInit() { - MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_CLIENT, con_say, this, "Say in chat"); - MACRO_REGISTER_COMMAND("say_team", "r", CFGFLAG_CLIENT, con_sayteam, this, "Say in team chat"); - MACRO_REGISTER_COMMAND("chat", "s", CFGFLAG_CLIENT, con_chat, this, "Enable chat with all/team mode"); + Console()->Register("say", "r", CFGFLAG_CLIENT, ConSay, this, "Say in chat"); + Console()->Register("say_team", "r", CFGFLAG_CLIENT, ConSayTeam, this, "Say in team chat"); + Console()->Register("chat", "s", CFGFLAG_CLIENT, ConChat, this, "Enable chat with all/team mode"); } -bool CHAT::on_input(INPUT_EVENT e) +bool CChat::OnInput(IInput::CEvent e) { - if(mode == MODE_NONE) + if(m_Mode == MODE_NONE) return false; - if(e.flags&INPFLAG_PRESS && e.key == KEY_ESCAPE) - mode = MODE_NONE; - else if(e.flags&INPFLAG_PRESS && (e.key == KEY_RETURN || e.key == KEY_KP_ENTER)) + if(e.m_Flags&IInput::FLAG_PRESS && e.m_Key == KEY_ESCAPE) + m_Mode = MODE_NONE; + else if(e.m_Flags&IInput::FLAG_PRESS && (e.m_Key == KEY_RETURN || e.m_Key == KEY_KP_ENTER)) { - if(input.get_string()[0]) - gameclient.chat->say(mode == MODE_ALL ? 0 : 1, input.get_string()); - mode = MODE_NONE; + if(m_Input.GetString()[0]) + Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString()); + m_Mode = MODE_NONE; } else - input.process_input(e); + m_Input.ProcessInput(e); return true; } -void CHAT::enable_mode(int team) +void CChat::EnableMode(int Team) { - if(mode == MODE_NONE) + if(m_Mode == MODE_NONE) { - if(team) - mode = MODE_TEAM; + if(Team) + m_Mode = MODE_TEAM; else - mode = MODE_ALL; + m_Mode = MODE_ALL; - input.clear(); - inp_clear_events(); + m_Input.Clear(); + Input()->ClearEvents(); } } -void CHAT::on_message(int msgtype, void *rawmsg) +void CChat::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_CHAT) + if(MsgType == NETMSGTYPE_SV_CHAT) { - NETMSG_SV_CHAT *msg = (NETMSG_SV_CHAT *)rawmsg; - add_line(msg->cid, msg->team, msg->message); + CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg; + AddLine(pMsg->m_Cid, pMsg->m_Team, pMsg->m_pMessage); } } -void CHAT::add_line(int client_id, int team, const char *line) +void CChat::AddLine(int ClientId, int Team, const char *pLine) { - current_line = (current_line+1)%MAX_LINES; - lines[current_line].time = time_get(); - lines[current_line].client_id = client_id; - lines[current_line].team = team; - lines[current_line].name_color = -2; - - if(client_id == -1) // server message + char *p = const_cast<char*>(pLine); + while(*p) { - str_copy(lines[current_line].name, "*** ", sizeof(lines[current_line].name)); - str_format(lines[current_line].text, sizeof(lines[current_line].text), "%s", line); - } - else - { - if(gameclient.clients[client_id].team == -1) - lines[current_line].name_color = -1; + pLine = p; + // find line seperator and strip multiline + while(*p) + { + if(*p++ == '\n') + { + *(p-1) = 0; + break; + } + } - if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) + m_CurrentLine = (m_CurrentLine+1)%MAX_LINES; + m_aLines[m_CurrentLine].m_Time = time_get(); + m_aLines[m_CurrentLine].m_ClientId = ClientId; + m_aLines[m_CurrentLine].m_Team = Team; + m_aLines[m_CurrentLine].m_NameColor = -2; + + if(ClientId == -1) // server message + { + str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName)); + str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine); + } + else { - if(gameclient.clients[client_id].team == 0) - lines[current_line].name_color = 0; - else if(gameclient.clients[client_id].team == 1) - lines[current_line].name_color = 1; + if(m_pClient->m_aClients[ClientId].m_Team == -1) + m_aLines[m_CurrentLine].m_NameColor = -1; + + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) + { + if(m_pClient->m_aClients[ClientId].m_Team == 0) + m_aLines[m_CurrentLine].m_NameColor = 0; + else if(m_pClient->m_aClients[ClientId].m_Team == 1) + m_aLines[m_CurrentLine].m_NameColor = 1; + } + + str_copy(m_aLines[m_CurrentLine].m_aName, m_pClient->m_aClients[ClientId].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName)); + str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine); } - str_copy(lines[current_line].name, gameclient.clients[client_id].name, sizeof(lines[current_line].name)); - str_format(lines[current_line].text, sizeof(lines[current_line].text), ": %s", line); + char aBuf[1024]; + str_format(aBuf, sizeof(aBuf), "[chat]%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); + Console()->Print(aBuf); } - + // play sound - if(client_id >= 0) - gameclient.sounds->play(SOUNDS::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0)); + if(ClientId >= 0) + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0)); else - gameclient.sounds->play(SOUNDS::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0)); - - dbg_msg("chat", "%s%s", lines[current_line].name, lines[current_line].text); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0)); } -void CHAT::on_render() +void CChat::OnRender() { Graphics()->MapScreen(0,0,300*Graphics()->ScreenAspect(),300); float x = 10.0f; float y = 300.0f-20.0f; - if(mode != MODE_NONE) + if(m_Mode != MODE_NONE) { // render chat input - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, x, y, 8.0f, TEXTFLAG_RENDER); - cursor.line_width = 200.0f; + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); + Cursor.m_LineWidth = 200.0f; - if(mode == MODE_ALL) - gfx_text_ex(&cursor, localize("All"), -1); - else if(mode == MODE_TEAM) - gfx_text_ex(&cursor, localize("Team"), -1); + if(m_Mode == MODE_ALL) + TextRender()->TextEx(&Cursor, Localize("All"), -1); + else if(m_Mode == MODE_TEAM) + TextRender()->TextEx(&Cursor, Localize("Team"), -1); else - gfx_text_ex(&cursor, localize("Chat"), -1); + TextRender()->TextEx(&Cursor, Localize("Chat"), -1); - gfx_text_ex(&cursor, ": ", -1); + TextRender()->TextEx(&Cursor, ": ", -1); - gfx_text_ex(&cursor, input.get_string(), input.cursor_offset()); - TEXT_CURSOR marker = cursor; - gfx_text_ex(&marker, "|", -1); - gfx_text_ex(&cursor, input.get_string()+input.cursor_offset(), -1); + TextRender()->TextEx(&Cursor, m_Input.GetString(), m_Input.GetCursorOffset()); + CTextCursor Marker = Cursor; + TextRender()->TextEx(&Marker, "|", -1); + TextRender()->TextEx(&Cursor, m_Input.GetString()+m_Input.GetCursorOffset(), -1); } y -= 8; int i; + int64 Now = time_get(); for(i = 0; i < MAX_LINES; i++) { - int r = ((current_line-i)+MAX_LINES)%MAX_LINES; - if(time_get() > lines[r].time+15*time_freq()) + int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES; + if(Now > m_aLines[r].m_Time+15*time_freq()) break; - float begin = x; - float fontsize = 7.0f; + float Begin = x; + float FontSize = 7.0f; // get the y offset - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, begin, 0, fontsize, 0); - cursor.line_width = 200.0f; - gfx_text_ex(&cursor, lines[r].name, -1); - gfx_text_ex(&cursor, lines[r].text, -1); - y -= cursor.y + cursor.font_size; + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Begin, 0, FontSize, 0); + Cursor.m_LineWidth = 200.0f; + TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1); + TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1); + y -= Cursor.m_Y + Cursor.m_FontSize; // cut off if msgs waste too much space if(y < 200.0f) break; // reset the cursor - gfx_text_set_cursor(&cursor, begin, y, fontsize, TEXTFLAG_RENDER); - cursor.line_width = 200.0f; + TextRender()->SetCursor(&Cursor, Begin, y, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = 200.0f; // render name - gfx_text_color(0.8f,0.8f,0.8f,1); - if(lines[r].client_id == -1) - gfx_text_color(1,1,0.5f,1); // system - else if(lines[r].team) - gfx_text_color(0.45f,0.9f,0.45f,1); // team message - else if(lines[r].name_color == 0) - gfx_text_color(1.0f,0.5f,0.5f,1); // red - else if(lines[r].name_color == 1) - gfx_text_color(0.7f,0.7f,1.0f,1); // blue - else if(lines[r].name_color == -1) - gfx_text_color(0.75f,0.5f,0.75f, 1); // spectator + TextRender()->TextColor(0.8f,0.8f,0.8f,1); + if(m_aLines[r].m_ClientId == -1) + TextRender()->TextColor(1,1,0.5f,1); // system + else if(m_aLines[r].m_Team) + TextRender()->TextColor(0.45f,0.9f,0.45f,1); // team message + else if(m_aLines[r].m_NameColor == 0) + TextRender()->TextColor(1.0f,0.5f,0.5f,1); // red + else if(m_aLines[r].m_NameColor == 1) + TextRender()->TextColor(0.7f,0.7f,1.0f,1); // blue + else if(m_aLines[r].m_NameColor == -1) + TextRender()->TextColor(0.75f,0.5f,0.75f, 1); // spectator // render name - gfx_text_ex(&cursor, lines[r].name, -1); + TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1); // render line - gfx_text_color(1,1,1,1); - if(lines[r].client_id == -1) - gfx_text_color(1,1,0.5f,1); // system - else if(lines[r].team) - gfx_text_color(0.65f,1,0.65f,1); // team message + TextRender()->TextColor(1,1,1,1); + if(m_aLines[r].m_ClientId == -1) + TextRender()->TextColor(1,1,0.5f,1); // system + else if(m_aLines[r].m_Team) + TextRender()->TextColor(0.65f,1,0.65f,1); // team message - gfx_text_ex(&cursor, lines[r].text, -1); + TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1); } - gfx_text_color(1,1,1,1); + TextRender()->TextColor(1,1,1,1); } -void CHAT::say(int team, const char *line) +void CChat::Say(int Team, const char *pLine) { // send chat message - NETMSG_CL_SAY msg; - msg.team = team; - msg.message = line; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_Say Msg; + Msg.m_Team = Team; + Msg.m_pMessage = pLine; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h new file mode 100644 index 00000000..8a33e9e8 --- /dev/null +++ b/src/game/client/components/chat.h @@ -0,0 +1,60 @@ +#ifndef GAME_CLIENT_COMPONENTS_CHAT_H +#define GAME_CLIENT_COMPONENTS_CHAT_H +#include <game/client/component.h> +#include <game/client/lineinput.h> + +class CChat : public CComponent +{ + CLineInput m_Input; + + enum + { + MAX_LINES = 10, + }; + + struct CLine + { + int64 m_Time; + int m_ClientId; + int m_Team; + int m_NameColor; + char m_aName[64]; + char m_aText[512]; + }; + + CLine m_aLines[MAX_LINES]; + int m_CurrentLine; + + // chat + enum + { + MODE_NONE=0, + MODE_ALL, + MODE_TEAM, + }; + + int m_Mode; + + static void ConSay(IConsole::IResult *pResult, void *pUserData); + static void ConSayTeam(IConsole::IResult *pResult, void *pUserData); + static void ConChat(IConsole::IResult *pResult, void *pUserData); + +public: + CChat(); + + bool IsActive() const { return m_Mode != MODE_NONE; } + + void AddLine(int ClientId, int Team, const char *pLine); + + void EnableMode(int Team); + + void Say(int Team, const char *pLine); + + virtual void OnReset(); + virtual void OnConsoleInit(); + virtual void OnStateChange(int NewState, int OldState); + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); + virtual bool OnInput(IInput::CEvent Event); +}; +#endif diff --git a/src/game/client/components/chat.hpp b/src/game/client/components/chat.hpp deleted file mode 100644 index ca34237d..00000000 --- a/src/game/client/components/chat.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#include <game/client/component.hpp> -#include <game/client/lineinput.hpp> - -class CHAT : public COMPONENT -{ - LINEINPUT input; - - enum - { - MAX_LINES = 10, - }; - - struct LINE - { - int64 time; - int client_id; - int team; - int name_color; - char name[64]; - char text[512]; - }; - - LINE lines[MAX_LINES]; - int current_line; - - // chat - enum - { - MODE_NONE=0, - MODE_ALL, - MODE_TEAM, - }; - - int mode; - - static void con_say(void *result, void *user_data); - static void con_sayteam(void *result, void *user_data); - static void con_chat(void *result, void *user_data); - -public: - bool is_active() const { return mode != MODE_NONE; } - - void add_line(int client_id, int team, const char *line); - - void enable_mode(int team); - - void say(int team, const char *line); - - virtual void on_console_init(); - virtual void on_statechange(int new_state, int old_state); - virtual void on_render(); - virtual void on_message(int msgtype, void *rawmsg); - virtual bool on_input(INPUT_EVENT e); -}; diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 382cb134..7de85f69 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -1,26 +1,29 @@ -//#include "gc_console.hpp" +//#include "gc_console.h" #include <math.h> -#include <game/generated/gc_data.hpp> +#include <game/generated/client_data.h> #include <base/system.h> -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> - -#include <engine/e_ringbuffer.h> +#include <engine/shared/ringbuffer.h> +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/keys.h> +#include <engine/console.h> #include <cstring> #include <cstdio> -#include <game/client/ui.hpp> +#include <game/client/ui.h> -#include <game/version.hpp> +#include <game/version.h> -#include <game/client/lineinput.hpp> -#include <game/client/render.hpp> +#include <game/client/lineinput.h> +#include <game/client/render.h> +#include <game/client/components/menus.h> -#include "console.hpp" +#include "console.h" enum { @@ -30,479 +33,550 @@ enum CONSOLE_CLOSING, }; -CONSOLE::INSTANCE::INSTANCE(int t) +CGameConsole::CInstance::CInstance(CGameConsole *pGameConsole, int Type) { + m_pGameConsole = pGameConsole; // init ringbuffers //history = ringbuf_init(history_data, sizeof(history_data), RINGBUF_FLAG_RECYCLE); //backlog = ringbuf_init(backlog_data, sizeof(backlog_data), RINGBUF_FLAG_RECYCLE); - history_entry = 0x0; + m_pHistoryEntry = 0x0; - type = t; + m_Type = Type; - if(t == 0) - completion_flagmask = CFGFLAG_CLIENT; + if(Type == 0) + m_CompletionFlagmask = CFGFLAG_CLIENT; else - completion_flagmask = CFGFLAG_SERVER; + m_CompletionFlagmask = CFGFLAG_SERVER; - completion_buffer[0] = 0; - completion_chosen = -1; + m_aCompletionBuffer[0] = 0; + m_CompletionChosen = -1; - command = 0x0; + m_pCommand = 0x0; } -void CONSOLE::INSTANCE::execute_line(const char *line) +void CGameConsole::CInstance::ExecuteLine(const char *pLine) { - if(type == 0) - console_execute_line(line); + if(m_Type == 0) + m_pGameConsole->m_pConsole->ExecuteLine(pLine); else { - if(client_rcon_authed()) - client_rcon(line); + if(m_pGameConsole->Client()->RconAuthed()) + m_pGameConsole->Client()->Rcon(pLine); else - client_rcon_auth("", line); + m_pGameConsole->Client()->RconAuth("", pLine); } } -void CONSOLE::INSTANCE::possible_commands_complete_callback(const char *str, void *user) +void CGameConsole::CInstance::PossibleCommandsCompleteCallback(const char *pStr, void *pUser) { - CONSOLE::INSTANCE *instance = (CONSOLE::INSTANCE *)user; - if(instance->completion_chosen == instance->completion_enumeration_count) - instance->input.set(str); - instance->completion_enumeration_count++; + CGameConsole::CInstance *pInstance = (CGameConsole::CInstance *)pUser; + if(pInstance->m_CompletionChosen == pInstance->m_CompletionEnumerationCount) + pInstance->m_Input.Set(pStr); + pInstance->m_CompletionEnumerationCount++; } -void CONSOLE::INSTANCE::on_input(INPUT_EVENT e) +void CGameConsole::CInstance::OnInput(IInput::CEvent Event) { - bool handled = false; + bool Handled = false; - if(e.flags&INPFLAG_PRESS) + if(Event.m_Flags&IInput::FLAG_PRESS) { - if(e.key == KEY_RETURN || e.key == KEY_KP_ENTER) + if(Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER) { - if(input.get_string()[0]) + if(m_Input.GetString()[0]) { - char *entry = history.Allocate(input.get_length()+1); - mem_copy(entry, input.get_string(), input.get_length()+1); - - execute_line(input.get_string()); - input.clear(); - history_entry = 0x0; + char *pEntry = m_History.Allocate(m_Input.GetLength()+1); + mem_copy(pEntry, m_Input.GetString(), m_Input.GetLength()+1); + ExecuteLine(m_Input.GetString()); + m_Input.Clear(); + m_pHistoryEntry = 0x0; } - handled = true; + Handled = true; } - else if (e.key == KEY_UP) + else if (Event.m_Key == KEY_UP) { - if (history_entry) + if (m_pHistoryEntry) { - char *test = history.Prev(history_entry); + char *pTest = m_History.Prev(m_pHistoryEntry); - if (test) - history_entry = test; + if (pTest) + m_pHistoryEntry = pTest; } else - history_entry = history.Last(); + m_pHistoryEntry = m_History.Last(); - if (history_entry) + if (m_pHistoryEntry) { - unsigned int len = strlen(history_entry); - if (len < sizeof(input) - 1) - input.set(history_entry); + unsigned int Len = str_length(m_pHistoryEntry); + if (Len < sizeof(m_Input) - 1) // TODO: WTF? + m_Input.Set(m_pHistoryEntry); } - handled = true; + Handled = true; } - else if (e.key == KEY_DOWN) + else if (Event.m_Key == KEY_DOWN) { - if (history_entry) - history_entry = history.Next(history_entry); + if (m_pHistoryEntry) + m_pHistoryEntry = m_History.Next(m_pHistoryEntry); - if (history_entry) + if (m_pHistoryEntry) { - unsigned int len = strlen(history_entry); - if (len < sizeof(input) - 1) - input.set(history_entry); + unsigned int Len = str_length(m_pHistoryEntry); + if (Len < sizeof(m_Input) - 1) // TODO: WTF? + m_Input.Set(m_pHistoryEntry); } else - input.clear(); - handled = true; + m_Input.Clear(); + Handled = true; } - else if(e.key == KEY_TAB) + else if(Event.m_Key == KEY_TAB) { - completion_chosen++; - completion_enumeration_count = 0; - console_possible_commands(completion_buffer, completion_flagmask, possible_commands_complete_callback, this); - - // handle wrapping - if(completion_enumeration_count && completion_chosen >= completion_enumeration_count) + if(m_Type == 0 || m_pGameConsole->Client()->RconAuthed()) { - completion_chosen %= completion_enumeration_count; - completion_enumeration_count = 0; - console_possible_commands(completion_buffer, completion_flagmask, possible_commands_complete_callback, this); + m_CompletionChosen++; + m_CompletionEnumerationCount = 0; + m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, PossibleCommandsCompleteCallback, this); + + // handle wrapping + if(m_CompletionEnumerationCount && m_CompletionChosen >= m_CompletionEnumerationCount) + { + m_CompletionChosen %= m_CompletionEnumerationCount; + m_CompletionEnumerationCount = 0; + m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, PossibleCommandsCompleteCallback, this); + } } } - - if(e.key != KEY_TAB) + else if(Event.m_Key == KEY_PAGEUP) + { + ++m_BacklogActPage; + } + else if(Event.m_Key == KEY_PAGEDOWN) { - completion_chosen = -1; - str_copy(completion_buffer, input.get_string(), sizeof(completion_buffer)); + --m_BacklogActPage; + if(m_BacklogActPage < 0) + m_BacklogActPage = 0; + } + } + + if(!Handled) + m_Input.ProcessInput(Event); + + if(Event.m_Flags&IInput::FLAG_PRESS) + { + if(Event.m_Key != KEY_TAB) + { + m_CompletionChosen = -1; + str_copy(m_aCompletionBuffer, m_Input.GetString(), sizeof(m_aCompletionBuffer)); } // find the current command { - char buf[64] = {0}; - const char *src = get_string(); + char aBuf[64] = {0}; + const char *pSrc = GetString(); int i = 0; - for(; i < (int)sizeof(buf) && *src && *src != ' ' && *src != ' '; i++, src++) - buf[i] = *src; - buf[i] = 0; + for(; i < (int)sizeof(aBuf) && *pSrc && *pSrc != ' ' && *pSrc != ' '; i++, pSrc++) + aBuf[i] = *pSrc; + aBuf[i] = 0; - command = console_get_command(buf); + m_pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf); } } - - if(!handled) - input.process_input(e); } -void CONSOLE::INSTANCE::print_line(const char *line) +void CGameConsole::CInstance::PrintLine(const char *pLine) { - int len = strlen(line); + int Len = str_length(pLine); - if (len > 255) - len = 255; + if (Len > 255) + Len = 255; - char *entry = backlog.Allocate(len+1); - mem_copy(entry, line, len+1); + char *pEntry = m_Backlog.Allocate(Len+1); + mem_copy(pEntry, pLine, Len); + pEntry[Len] = 0; } -CONSOLE::CONSOLE() -: local_console(0), remote_console(1) +CGameConsole::CGameConsole() +: m_LocalConsole(this, 0), m_RemoteConsole(this, 1) { - console_type = 0; - console_state = CONSOLE_CLOSED; - state_change_end = 0.0f; - state_change_duration = 0.1f; + m_ConsoleType = 0; + m_ConsoleState = CONSOLE_CLOSED; + m_StateChangeEnd = 0.0f; + m_StateChangeDuration = 0.1f; } -float CONSOLE::time_now() +float CGameConsole::TimeNow() { - static long long time_start = time_get(); - return float(time_get()-time_start)/float(time_freq()); + static long long s_TimeStart = time_get(); + return float(time_get()-s_TimeStart)/float(time_freq()); } -CONSOLE::INSTANCE *CONSOLE::current_console() +CGameConsole::CInstance *CGameConsole::CurrentConsole() { - if(console_type != 0) - return &remote_console; - return &local_console; + if(m_ConsoleType != 0) + return &m_RemoteConsole; + return &m_LocalConsole; } -void CONSOLE::on_reset() +void CGameConsole::OnReset() { } // only defined for 0<=t<=1 -static float console_scale_func(float t) +static float ConsoleScaleFunc(float t) { //return t; return sinf(acosf(1.0f-t)); } -struct RENDERINFO +struct CRenderInfo { - CONSOLE *self; - TEXT_CURSOR cursor; - const char *current_cmd; - int wanted_completion; - int enum_count; + CGameConsole *m_pSelf; + CTextCursor m_Cursor; + const char *m_pCurrentCmd; + int m_WantedCompletion; + int m_EnumCount; }; -void CONSOLE::possible_commands_render_callback(const char *str, void *user) +void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser) { - RENDERINFO *info = (RENDERINFO *)user; + CRenderInfo *pInfo = static_cast<CRenderInfo *>(pUser); - if(info->enum_count == info->wanted_completion) + if(pInfo->m_EnumCount == pInfo->m_WantedCompletion) { - float tw = gfx_text_width(info->cursor.font, info->cursor.font_size, str, -1); - info->self->Graphics()->TextureSet(-1); - info->self->Graphics()->QuadsBegin(); - info->self->Graphics()->SetColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,0.85f); - info->self->RenderTools()->draw_round_rect(info->cursor.x-3, info->cursor.y, tw+5, info->cursor.font_size+4, info->cursor.font_size/3); - info->self->Graphics()->QuadsEnd(); + float tw = pInfo->m_pSelf->TextRender()->TextWidth(pInfo->m_Cursor.m_pFont, pInfo->m_Cursor.m_FontSize, pStr, -1); + pInfo->m_pSelf->Graphics()->TextureSet(-1); + pInfo->m_pSelf->Graphics()->QuadsBegin(); + pInfo->m_pSelf->Graphics()->SetColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,0.85f); + pInfo->m_pSelf->RenderTools()->DrawRoundRect(pInfo->m_Cursor.m_X-3, pInfo->m_Cursor.m_Y, tw+5, pInfo->m_Cursor.m_FontSize+4, pInfo->m_Cursor.m_FontSize/3); + pInfo->m_pSelf->Graphics()->QuadsEnd(); - gfx_text_color(0.05f, 0.05f, 0.05f,1); - gfx_text_ex(&info->cursor, str, -1); + pInfo->m_pSelf->TextRender()->TextColor(0.05f, 0.05f, 0.05f,1); + pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1); } else { - const char *match_start = str_find_nocase(str, info->current_cmd); + const char *pMatchStart = str_find_nocase(pStr, pInfo->m_pCurrentCmd); - if(match_start) + if(pMatchStart) { - gfx_text_color(0.5f,0.5f,0.5f,1); - gfx_text_ex(&info->cursor, str, match_start-str); - gfx_text_color(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,1); - gfx_text_ex(&info->cursor, match_start, strlen(info->current_cmd)); - gfx_text_color(0.5f,0.5f,0.5f,1); - gfx_text_ex(&info->cursor, match_start+strlen(info->current_cmd), -1); + pInfo->m_pSelf->TextRender()->TextColor(0.5f,0.5f,0.5f,1); + pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, pMatchStart-pStr); + pInfo->m_pSelf->TextRender()->TextColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,1); + pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pMatchStart, str_length(pInfo->m_pCurrentCmd)); + pInfo->m_pSelf->TextRender()->TextColor(0.5f,0.5f,0.5f,1); + pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pMatchStart+str_length(pInfo->m_pCurrentCmd), -1); } else { - gfx_text_color(0.75f,0.75f,0.75f,1); - gfx_text_ex(&info->cursor, str, -1); + pInfo->m_pSelf->TextRender()->TextColor(0.75f,0.75f,0.75f,1); + pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1); } } - info->enum_count++; - info->cursor.x += 7.0f; + pInfo->m_EnumCount++; + pInfo->m_Cursor.m_X += 7.0f; } -void CONSOLE::on_render() +void CGameConsole::OnRender() { - CUIRect screen = *UI()->Screen(); - float console_max_height = screen.h*3/5.0f; - float console_height; + CUIRect Screen = *UI()->Screen(); + float ConsoleMaxHeight = Screen.h*3/5.0f; + float ConsoleHeight; - float progress = (time_now()-(state_change_end-state_change_duration))/float(state_change_duration); + float Progress = (TimeNow()-(m_StateChangeEnd-m_StateChangeDuration))/float(m_StateChangeDuration); - if (progress >= 1.0f) + if (Progress >= 1.0f) { - if (console_state == CONSOLE_CLOSING) - console_state = CONSOLE_CLOSED; - else if (console_state == CONSOLE_OPENING) - console_state = CONSOLE_OPEN; + if (m_ConsoleState == CONSOLE_CLOSING) + m_ConsoleState = CONSOLE_CLOSED; + else if (m_ConsoleState == CONSOLE_OPENING) + m_ConsoleState = CONSOLE_OPEN; - progress = 1.0f; + Progress = 1.0f; } - if (console_state == CONSOLE_OPEN && config.cl_editor) - toggle(0); + if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor) + Toggle(0); - if (console_state == CONSOLE_CLOSED) + if (m_ConsoleState == CONSOLE_CLOSED) return; - if (console_state == CONSOLE_OPEN) - inp_mouse_mode_absolute(); + if (m_ConsoleState == CONSOLE_OPEN) + Input()->MouseModeAbsolute(); - float console_height_scale; + float ConsoleHeightScale; - if (console_state == CONSOLE_OPENING) - console_height_scale = console_scale_func(progress); - else if (console_state == CONSOLE_CLOSING) - console_height_scale = console_scale_func(1.0f-progress); + if (m_ConsoleState == CONSOLE_OPENING) + ConsoleHeightScale = ConsoleScaleFunc(Progress); + else if (m_ConsoleState == CONSOLE_CLOSING) + ConsoleHeightScale = ConsoleScaleFunc(1.0f-Progress); else //if (console_state == CONSOLE_OPEN) - console_height_scale = console_scale_func(1.0f); + ConsoleHeightScale = ConsoleScaleFunc(1.0f); - console_height = console_height_scale*console_max_height; + ConsoleHeight = ConsoleHeightScale*ConsoleMaxHeight; - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); // do console shadow Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - Graphics()->SetColorVertex(0, 0,0,0, 0.5f); - Graphics()->SetColorVertex(1, 0,0,0, 0.5f); - Graphics()->SetColorVertex(2, 0,0,0, 0.0f); - Graphics()->SetColorVertex(3, 0,0,0, 0.0f); - Graphics()->QuadsDrawTL(0,console_height,screen.w,10.0f); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, 0,0,0, 0.5f), + IGraphics::CColorVertex(1, 0,0,0, 0.5f), + IGraphics::CColorVertex(2, 0,0,0, 0.0f), + IGraphics::CColorVertex(3, 0,0,0, 0.0f)}; + Graphics()->SetColorVertex(Array, 4); + IGraphics::CQuadItem QuadItem(0, ConsoleHeight, Screen.w, 10.0f); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do background - Graphics()->TextureSet(data->images[IMAGE_CONSOLE_BG].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BG].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f); - if(console_type != 0) + if(m_ConsoleType != 0) Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f); - Graphics()->QuadsSetSubset(0,-console_height*0.075f,screen.w*0.075f*0.5f,0); - Graphics()->QuadsDrawTL(0,0,screen.w,console_height); + Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0); + QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do small bar shadow Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - Graphics()->SetColorVertex(0, 0,0,0, 0.0f); - Graphics()->SetColorVertex(1, 0,0,0, 0.0f); - Graphics()->SetColorVertex(2, 0,0,0, 0.25f); - Graphics()->SetColorVertex(3, 0,0,0, 0.25f); - Graphics()->QuadsDrawTL(0,console_height-20,screen.w,10); + Array[0] = IGraphics::CColorVertex(0, 0,0,0, 0.0f); + Array[1] = IGraphics::CColorVertex(1, 0,0,0, 0.0f); + Array[2] = IGraphics::CColorVertex(2, 0,0,0, 0.25f); + Array[3] = IGraphics::CColorVertex(3, 0,0,0, 0.25f); + Graphics()->SetColorVertex(Array, 4); + QuadItem = IGraphics::CQuadItem(0, ConsoleHeight-20, Screen.w, 10); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // do the lower bar - Graphics()->TextureSet(data->images[IMAGE_CONSOLE_BAR].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BAR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f); - Graphics()->QuadsSetSubset(0,0.1f,screen.w*0.015f,1-0.1f); - Graphics()->QuadsDrawTL(0,console_height-10.0f,screen.w,10.0f); + Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f); + QuadItem = IGraphics::CQuadItem(0,ConsoleHeight-10.0f,Screen.w,10.0f); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - console_height -= 22.0f; + ConsoleHeight -= 22.0f; - INSTANCE *console = current_console(); + CInstance *pConsole = CurrentConsole(); { - float font_size = 10.0f; - float row_height = font_size*1.25f; + float FontSize = 10.0f; + float RowHeight = FontSize*1.25f; float x = 3; - float y = console_height - row_height - 2; + float y = ConsoleHeight - RowHeight - 2; // render prompt - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, x, y, font_size, TEXTFLAG_RENDER); - - RENDERINFO info; - info.self = this; - info.wanted_completion = console->completion_chosen; - info.enum_count = 0; - info.current_cmd = console->completion_buffer; - gfx_text_set_cursor(&info.cursor, x, y+12.0f, font_size, TEXTFLAG_RENDER); - - const char *prompt = "> "; - if(console_type) + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); + + CRenderInfo Info; + Info.m_pSelf = this; + Info.m_WantedCompletion = pConsole->m_CompletionChosen; + Info.m_EnumCount = 0; + Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer; + TextRender()->SetCursor(&Info.m_Cursor, x, y+12.0f, FontSize, TEXTFLAG_RENDER); + + const char *pPrompt = "> "; + if(m_ConsoleType) { - if(client_state() == CLIENTSTATE_ONLINE) + if(Client()->State() == IClient::STATE_ONLINE) { - if(client_rcon_authed()) - prompt = "rcon> "; + if(Client()->RconAuthed()) + pPrompt = "rcon> "; else - prompt = "ENTER PASSWORD> "; + pPrompt = "ENTER PASSWORD> "; } else - prompt = "NOT CONNECTED> "; + pPrompt = "NOT CONNECTED> "; } - gfx_text_ex(&cursor, prompt, -1); - - // render console input - gfx_text_ex(&cursor, console->input.get_string(), console->input.cursor_offset()); - TEXT_CURSOR marker = cursor; - gfx_text_ex(&marker, "|", -1); - gfx_text_ex(&cursor, console->input.get_string()+console->input.cursor_offset(), -1); + TextRender()->TextEx(&Cursor, pPrompt, -1); + x = Cursor.m_X; // render version - char buf[128]; - str_format(buf, sizeof(buf), "v%s", GAME_VERSION); - float version_width = gfx_text_width(0, font_size, buf, -1); - gfx_text(0, screen.w-version_width-5, y, font_size, buf, -1); - - // render possible commands - if(console->input.get_string()[0] != 0) + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "v%s", GAME_VERSION); + float VersionWidth = TextRender()->TextWidth(0, FontSize, aBuf, -1); + TextRender()->Text(0, Screen.w-VersionWidth-5, y, FontSize, aBuf, -1); + + // render console input (wrap line) + int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - (VersionWidth + 10 + x)); + y -= (Lines - 1) * FontSize; + TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = Screen.w - (VersionWidth + 10 + x); + + //hide rcon password + char aInputString[256]; + str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString)); + if(m_ConsoleType && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed()) { - console_possible_commands(console->completion_buffer, console->completion_flagmask, possible_commands_render_callback, &info); + for(int i = 0; i < pConsole->m_Input.GetLength(); ++i) + aInputString[i] = '*'; + } - if(info.enum_count <= 0) + TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset()); + CTextCursor Marker = Cursor; + TextRender()->TextEx(&Marker, "|", -1); + TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1); + + // render possible commands + if(m_ConsoleType == 0 || Client()->RconAuthed()) + { + if(pConsole->m_Input.GetString()[0] != 0) { - if(console->command) + m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, PossibleCommandsRenderCallback, &Info); + + if(Info.m_EnumCount <= 0) { - - char buf[512]; - str_format(buf, sizeof(buf), "Help: %s ", console->command->help); - gfx_text_ex(&info.cursor, buf, -1); - gfx_text_color(0.75f, 0.75f, 0.75f, 1); - str_format(buf, sizeof(buf), "Syntax: %s %s", console->command->name, console->command->params); - gfx_text_ex(&info.cursor, buf, -1); + if(pConsole->m_pCommand) + { + + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_pCommand->m_pHelp); + TextRender()->TextEx(&Info.m_Cursor, aBuf, -1); + TextRender()->TextColor(0.75f, 0.75f, 0.75f, 1); + str_format(aBuf, sizeof(aBuf), "Syntax: %s %s", pConsole->m_pCommand->m_pName, pConsole->m_pCommand->m_pParams); + TextRender()->TextEx(&Info.m_Cursor, aBuf, -1); + } } } } - gfx_text_color(1,1,1,1); + TextRender()->TextColor(1,1,1,1); - // render log - y -= row_height; - char *entry = console->backlog.Last(); - while (y > 0.0f && entry) + // render log (actual page, wrap lines) + char *pEntry = pConsole->m_Backlog.Last(); + for(int Page = 0, Lines = 0; Page <= pConsole->m_BacklogActPage; ++Page, Lines = 0) { - gfx_text(0, x, y, font_size, entry, -1); - y -= row_height; + // next page when lines reach the top + while(y - Lines * RowHeight > RowHeight && pEntry) + { + Lines += TextRender()->TextLineCount(0, FontSize, pEntry, Screen.w-10); + // just render output from actual backlog page (render bottom up) + if(Page == pConsole->m_BacklogActPage) + { + TextRender()->SetCursor(&Cursor, 0, y - Lines * RowHeight, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = Screen.w-10; + TextRender()->TextEx(&Cursor, pEntry, -1); + } + pEntry = pConsole->m_Backlog.Prev(pEntry); + } - entry = console->backlog.Prev(entry); + // actual backlog page number is too high, render last available page (current checked one, render top down) + if(!pEntry && Page < pConsole->m_BacklogActPage) + { + pConsole->m_BacklogActPage = Page; + pEntry = pConsole->m_Backlog.First(); + while(Lines > 0 && pEntry) + { + TextRender()->SetCursor(&Cursor, 0, y - Lines * RowHeight, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = Screen.w-10; + Cursor.m_LineCount = 1; + TextRender()->TextEx(&Cursor, pEntry, -1); + Lines -= Cursor.m_LineCount; + pEntry = pConsole->m_Backlog.Next(pEntry); + } + break; + } } } } -void CONSOLE::on_message(int msgtype, void *rawmsg) +void CGameConsole::OnMessage(int MsgType, void *pRawMsg) { } -bool CONSOLE::on_input(INPUT_EVENT e) +bool CGameConsole::OnInput(IInput::CEvent Event) { - if(console_state == CONSOLE_CLOSED) + if(m_ConsoleState == CONSOLE_CLOSED) return false; - if(e.key >= KEY_F1 && e.key <= KEY_F15) + if(Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F15) return false; - if(e.key == KEY_ESCAPE && (e.flags&INPFLAG_PRESS)) - toggle(console_type); + if(Event.m_Key == KEY_ESCAPE && (Event.m_Flags&IInput::FLAG_PRESS)) + Toggle(m_ConsoleType); else - current_console()->on_input(e); + CurrentConsole()->OnInput(Event); return true; } -void CONSOLE::toggle(int type) +void CGameConsole::Toggle(int Type) { - if(console_type != type && (console_state == CONSOLE_OPEN || console_state == CONSOLE_OPENING)) + if(m_ConsoleType != Type && (m_ConsoleState == CONSOLE_OPEN || m_ConsoleState == CONSOLE_OPENING)) { // don't toggle console, just switch what console to use } else { - if (console_state == CONSOLE_CLOSED || console_state == CONSOLE_OPEN) + if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_OPEN) { - state_change_end = time_now()+state_change_duration; + m_StateChangeEnd = TimeNow()+m_StateChangeDuration; } else { - float progress = state_change_end-time_now(); - float reversed_progress = state_change_duration-progress; + float Progress = m_StateChangeEnd-TimeNow(); + float ReversedProgress = m_StateChangeDuration-Progress; - state_change_end = time_now()+reversed_progress; + m_StateChangeEnd = TimeNow()+ReversedProgress; } - if (console_state == CONSOLE_CLOSED || console_state == CONSOLE_CLOSING) + if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_CLOSING) { - inp_mouse_mode_absolute(); - console_state = CONSOLE_OPENING; + Input()->MouseModeAbsolute(); + m_pClient->m_pMenus->UseMouseButtons(false); + m_ConsoleState = CONSOLE_OPENING; } else { - inp_mouse_mode_relative(); - console_state = CONSOLE_CLOSING; + Input()->MouseModeRelative(); + m_pClient->m_pMenus->UseMouseButtons(true); + m_ConsoleState = CONSOLE_CLOSING; } } - console_type = type; + m_ConsoleType = Type; } -void CONSOLE::con_toggle_local_console(void *result, void *user_data) +void CGameConsole::ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData) { - ((CONSOLE *)user_data)->toggle(0); + ((CGameConsole *)pUserData)->Toggle(0); } -void CONSOLE::con_toggle_remote_console(void *result, void *user_data) +void CGameConsole::ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData) { - ((CONSOLE *)user_data)->toggle(1); + ((CGameConsole *)pUserData)->Toggle(1); } -void CONSOLE::client_console_print_callback(const char *str, void *user_data) +void CGameConsole::ClientConsolePrintCallback(const char *pStr, void *pUserData) { - ((CONSOLE *)user_data)->local_console.print_line(str); + ((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr); } -void CONSOLE::print_line(int type, const char *line) +void CGameConsole::PrintLine(int Type, const char *pLine) { - if(type == 0) - local_console.print_line(line); - else if(type == 1) - remote_console.print_line(line); + if(Type == 0) + m_LocalConsole.PrintLine(pLine); + else if(Type == 1) + m_RemoteConsole.PrintLine(pLine); } -void CONSOLE::on_console_init() +void CGameConsole::OnConsoleInit() { + m_pConsole = Kernel()->RequestInterface<IConsole>(); + // - console_register_print_callback(client_console_print_callback, this); + Console()->RegisterPrintCallback(ClientConsolePrintCallback, this); - MACRO_REGISTER_COMMAND("toggle_local_console", "", CFGFLAG_CLIENT, con_toggle_local_console, this, "Toggle local console"); - MACRO_REGISTER_COMMAND("toggle_remote_console", "", CFGFLAG_CLIENT, con_toggle_remote_console, this, "Toggle remote console"); + Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console"); + Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console"); } /* diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h new file mode 100644 index 00000000..b88c6349 --- /dev/null +++ b/src/game/client/components/console.h @@ -0,0 +1,72 @@ +#ifndef GAME_CLIENT_COMPONENTS_CONSOLE_H +#define GAME_CLIENT_COMPONENTS_CONSOLE_H +#include <engine/shared/ringbuffer.h> +#include <game/client/component.h> +#include <game/client/lineinput.h> + +class CGameConsole : public CComponent +{ + class CInstance + { + public: + TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> m_Backlog; + TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> m_History; + char *m_pHistoryEntry; + + CLineInput m_Input; + int m_Type; + int m_CompletionEnumerationCount; + int m_BacklogActPage; + + public: + CGameConsole *m_pGameConsole; + + char m_aCompletionBuffer[128]; + int m_CompletionChosen; + int m_CompletionFlagmask; + + IConsole::CCommandInfo *m_pCommand; + + CInstance(CGameConsole *pGameConsole, int t); + + void ExecuteLine(const char *pLine); + + void OnInput(IInput::CEvent Event); + void PrintLine(const char *pLine); + + const char *GetString() const { return m_Input.GetString(); } + static void PossibleCommandsCompleteCallback(const char *pStr, void *pUser); + }; + + class IConsole *m_pConsole; + + CInstance m_LocalConsole; + CInstance m_RemoteConsole; + + CInstance *CurrentConsole(); + float TimeNow(); + + int m_ConsoleType; + int m_ConsoleState; + float m_StateChangeEnd; + float m_StateChangeDuration; + + void Toggle(int Type); + + static void PossibleCommandsRenderCallback(const char *pStr, void *pUser); + static void ClientConsolePrintCallback(const char *pStr, void *pUserData); + static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData); + static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData); + +public: + CGameConsole(); + + void PrintLine(int Type, const char *pLine); + + virtual void OnConsoleInit(); + virtual void OnReset(); + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); + virtual bool OnInput(IInput::CEvent Events); +}; +#endif diff --git a/src/game/client/components/console.hpp b/src/game/client/components/console.hpp deleted file mode 100644 index 78da98b8..00000000 --- a/src/game/client/components/console.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#include <engine/e_client_interface.h> -#include <engine/e_ringbuffer.h> -#include <game/client/component.hpp> -#include <game/client/lineinput.hpp> - -class CONSOLE : public COMPONENT -{ - class INSTANCE - { - public: - TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> backlog; - TStaticRingBuffer<char, 64*1024, CRingBufferBase::FLAG_RECYCLE> history; - char *history_entry; - - LINEINPUT input; - - int type; - int completion_enumeration_count; - - public: - char completion_buffer[128]; - int completion_chosen; - int completion_flagmask; - - COMMAND *command; - - INSTANCE(int t); - - void execute_line(const char *line); - - void on_input(INPUT_EVENT e); - void print_line(const char *line); - - const char *get_string() const { return input.get_string(); } - - static void possible_commands_complete_callback(const char *str, void *user); - }; - - INSTANCE local_console; - INSTANCE remote_console; - - INSTANCE *current_console(); - float time_now(); - - int console_type; - int console_state; - float state_change_end; - float state_change_duration; - - - void toggle(int type); - - static void possible_commands_render_callback(const char *str, void *user); - static void client_console_print_callback(const char *str, void *user_data); - static void con_toggle_local_console(void *result, void *user_data); - static void con_toggle_remote_console(void *result, void *user_data); - -public: - CONSOLE(); - - void print_line(int type, const char *line); - - virtual void on_console_init(); - virtual void on_reset(); - virtual void on_render(); - virtual void on_message(int msgtype, void *rawmsg); - virtual bool on_input(INPUT_EVENT e); -}; diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index b48fb198..714f8b0c 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -1,210 +1,215 @@ -#include <engine/e_client_interface.h> -#include <base/math.hpp> -#include <game/collision.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/component.hpp> -#include <game/client/components/chat.hpp> -#include <game/client/components/menus.hpp> +#include <base/math.h> -#include "controls.hpp" +#include <engine/shared/config.h> -CONTROLS::CONTROLS() +#include <game/collision.h> +#include <game/client/gameclient.h> +#include <game/client/component.h> +#include <game/client/components/chat.h> +#include <game/client/components/menus.h> + +#include "controls.h" + +CControls::CControls() { } -static void con_key_input_state(void *result, void *user_data) +static void ConKeyInputState(IConsole::IResult *pResult, void *pUserData) { - ((int *)user_data)[0] = console_arg_int(result, 0); + ((int *)pUserData)[0] = pResult->GetInteger(0); } -static void con_key_input_counter(void *result, void *user_data) +static void ConKeyInputCounter(IConsole::IResult *pResult, void *pUserData) { - int *v = (int *)user_data; - if(((*v)&1) != console_arg_int(result, 0)) + int *v = (int *)pUserData; + if(((*v)&1) != pResult->GetInteger(0)) (*v)++; *v &= INPUT_STATE_MASK; } -struct INPUTSET +struct CInputSet { - CONTROLS *controls; - int *variable; - int value; + CControls *m_pControls; + int *m_pVariable; + int m_Value; }; -static void con_key_input_set(void *result, void *user_data) +static void ConKeyInputSet(IConsole::IResult *pResult, void *pUserData) { - INPUTSET *set = (INPUTSET *)user_data; - if(console_arg_int(result, 0)) - *set->variable = set->value; + CInputSet *pSet = (CInputSet *)pUserData; + if(pResult->GetInteger(0)) + *pSet->m_pVariable = pSet->m_Value; } -static void con_key_input_nextprev_weapon(void *result, void *user_data) +static void ConKeyInputNextPrevWeapon(IConsole::IResult *pResult, void *pUserData) { - INPUTSET *set = (INPUTSET *)user_data; - con_key_input_counter(result, set->variable); - set->controls->input_data.wanted_weapon = 0; + CInputSet *pSet = (CInputSet *)pUserData; + ConKeyInputCounter(pResult, pSet->m_pVariable); + pSet->m_pControls->m_InputData.m_WantedWeapon = 0; } -void CONTROLS::on_console_init() +void CControls::OnConsoleInit() { // game commands - MACRO_REGISTER_COMMAND("+left", "", CFGFLAG_CLIENT, con_key_input_state, &input_direction_left, "Move left"); - MACRO_REGISTER_COMMAND("+right", "", CFGFLAG_CLIENT, con_key_input_state, &input_direction_right, "Move right"); - MACRO_REGISTER_COMMAND("+jump", "", CFGFLAG_CLIENT, con_key_input_state, &input_data.jump, "Jump"); - MACRO_REGISTER_COMMAND("+hook", "", CFGFLAG_CLIENT, con_key_input_state, &input_data.hook, "Hook"); - MACRO_REGISTER_COMMAND("+fire", "", CFGFLAG_CLIENT, con_key_input_counter, &input_data.fire, "Fire"); - - { static INPUTSET set = {this, &input_data.wanted_weapon, 1}; MACRO_REGISTER_COMMAND("+weapon1", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to hammer"); } - { static INPUTSET set = {this, &input_data.wanted_weapon, 2}; MACRO_REGISTER_COMMAND("+weapon2", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to gun"); } - { static INPUTSET set = {this, &input_data.wanted_weapon, 3}; MACRO_REGISTER_COMMAND("+weapon3", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to shotgun"); } - { static INPUTSET set = {this, &input_data.wanted_weapon, 4}; MACRO_REGISTER_COMMAND("+weapon4", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to grenade"); } - { static INPUTSET set = {this, &input_data.wanted_weapon, 5}; MACRO_REGISTER_COMMAND("+weapon5", "", CFGFLAG_CLIENT, con_key_input_set, (void *)&set, "Switch to rifle"); } - - { static INPUTSET set = {this, &input_data.next_weapon, 0}; MACRO_REGISTER_COMMAND("+nextweapon", "", CFGFLAG_CLIENT, con_key_input_nextprev_weapon, (void *)&set, "Switch to next weapon"); } - { static INPUTSET set = {this, &input_data.prev_weapon, 0}; MACRO_REGISTER_COMMAND("+prevweapon", "", CFGFLAG_CLIENT, con_key_input_nextprev_weapon, (void *)&set, "Switch to previous weapon"); } + Console()->Register("+left", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionLeft, "Move left"); + Console()->Register("+right", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionRight, "Move right"); + Console()->Register("+jump", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Jump, "Jump"); + Console()->Register("+hook", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Hook, "Hook"); + Console()->Register("+fire", "", CFGFLAG_CLIENT, ConKeyInputCounter, &m_InputData.m_Fire, "Fire"); + + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 1}; Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); } + + { static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); } + { static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); } } -void CONTROLS::on_message(int msg, void *rawmsg) +void CControls::OnMessage(int Msg, void *pRawMsg) { - if(msg == NETMSGTYPE_SV_WEAPONPICKUP) + if(Msg == NETMSGTYPE_SV_WEAPONPICKUP) { - NETMSG_SV_WEAPONPICKUP *msg = (NETMSG_SV_WEAPONPICKUP *)rawmsg; - if(config.cl_autoswitch_weapons) - input_data.wanted_weapon = msg->weapon+1; + CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; + if(g_Config.m_ClAutoswitchWeapons) + m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; } } -int CONTROLS::snapinput(int *data) +int CControls::SnapInput(int *pData) { - static NETOBJ_PLAYER_INPUT last_data = {0}; - static int64 last_send_time = 0; - bool send = false; + static CNetObj_PlayerInput LastData = {0}; + static int64 LastSendTime = 0; + bool Send = false; // update player state - if(gameclient.chat->is_active()) - input_data.player_state = PLAYERSTATE_CHATTING; - else if(gameclient.menus->is_active()) - input_data.player_state = PLAYERSTATE_IN_MENU; + if(m_pClient->m_pChat->IsActive()) + m_InputData.m_PlayerState = PLAYERSTATE_CHATTING; + else if(m_pClient->m_pMenus->IsActive()) + m_InputData.m_PlayerState = PLAYERSTATE_IN_MENU; else - input_data.player_state = PLAYERSTATE_PLAYING; + m_InputData.m_PlayerState = PLAYERSTATE_PLAYING; - if(last_data.player_state != input_data.player_state) - send = true; + if(LastData.m_PlayerState != m_InputData.m_PlayerState) + Send = true; - last_data.player_state = input_data.player_state; + LastData.m_PlayerState = m_InputData.m_PlayerState; // we freeze the input if chat or menu is activated - if(input_data.player_state != PLAYERSTATE_PLAYING) + if(m_InputData.m_PlayerState != PLAYERSTATE_PLAYING) { - last_data.direction = 0; - last_data.hook = 0; - last_data.jump = 0; - input_data = last_data; + LastData.m_Direction = 0; + LastData.m_Hook = 0; + LastData.m_Jump = 0; + m_InputData = LastData; - input_direction_left = 0; - input_direction_right = 0; + m_InputDirectionLeft = 0; + m_InputDirectionRight = 0; - mem_copy(data, &input_data, sizeof(input_data)); + mem_copy(pData, &m_InputData, sizeof(m_InputData)); // send once a second just to be sure - if(time_get() > last_send_time + time_freq()) - send = true; + if(time_get() > LastSendTime + time_freq()) + Send = true; } else { - input_data.target_x = (int)mouse_pos.x; - input_data.target_y = (int)mouse_pos.y; - if(!input_data.target_x && !input_data.target_y) - input_data.target_y = 1; + m_InputData.m_TargetX = (int)m_MousePos.x; + m_InputData.m_TargetY = (int)m_MousePos.y; + if(!m_InputData.m_TargetX && !m_InputData.m_TargetY) + { + m_InputData.m_TargetX = 1; + m_MousePos.x = 1; + } // set direction - input_data.direction = 0; - if(input_direction_left && !input_direction_right) - input_data.direction = -1; - if(!input_direction_left && input_direction_right) - input_data.direction = 1; + m_InputData.m_Direction = 0; + if(m_InputDirectionLeft && !m_InputDirectionRight) + m_InputData.m_Direction = -1; + if(!m_InputDirectionLeft && m_InputDirectionRight) + m_InputData.m_Direction = 1; // stress testing - if(config.dbg_stress) + if(g_Config.m_DbgStress) { - float t = client_localtime(); - mem_zero(&input_data, sizeof(input_data)); - - input_data.direction = ((int)t/2)&1; - input_data.jump = ((int)t); - input_data.fire = ((int)(t*10)); - input_data.hook = ((int)(t*2))&1; - input_data.wanted_weapon = ((int)t)%NUM_WEAPONS; - input_data.target_x = (int)(sinf(t*3)*100.0f); - input_data.target_y = (int)(cosf(t*3)*100.0f); + float t = Client()->LocalTime(); + mem_zero(&m_InputData, sizeof(m_InputData)); + + m_InputData.m_Direction = ((int)t/2)&1; + m_InputData.m_Jump = ((int)t); + m_InputData.m_Fire = ((int)(t*10)); + m_InputData.m_Hook = ((int)(t*2))&1; + m_InputData.m_WantedWeapon = ((int)t)%NUM_WEAPONS; + m_InputData.m_TargetX = (int)(sinf(t*3)*100.0f); + m_InputData.m_TargetY = (int)(cosf(t*3)*100.0f); } // check if we need to send input - if(input_data.direction != last_data.direction) send = true; - else if(input_data.jump != last_data.jump) send = true; - else if(input_data.fire != last_data.fire) send = true; - else if(input_data.hook != last_data.hook) send = true; - else if(input_data.player_state != last_data.player_state) send = true; - else if(input_data.wanted_weapon != last_data.wanted_weapon) send = true; - else if(input_data.next_weapon != last_data.next_weapon) send = true; - else if(input_data.prev_weapon != last_data.prev_weapon) send = true; + if(m_InputData.m_Direction != LastData.m_Direction) Send = true; + else if(m_InputData.m_Jump != LastData.m_Jump) Send = true; + else if(m_InputData.m_Fire != LastData.m_Fire) Send = true; + else if(m_InputData.m_Hook != LastData.m_Hook) Send = true; + else if(m_InputData.m_PlayerState != LastData.m_PlayerState) Send = true; + else if(m_InputData.m_WantedWeapon != LastData.m_WantedWeapon) Send = true; + else if(m_InputData.m_NextWeapon != LastData.m_NextWeapon) Send = true; + else if(m_InputData.m_PrevWeapon != LastData.m_PrevWeapon) Send = true; // send at at least 10hz - if(time_get() > last_send_time + time_freq()/25) - send = true; + if(time_get() > LastSendTime + time_freq()/25) + Send = true; } // copy and return size - last_data = input_data; + LastData = m_InputData; - if(!send) + if(!Send) return 0; - last_send_time = time_get(); - mem_copy(data, &input_data, sizeof(input_data)); - return sizeof(input_data); + LastSendTime = time_get(); + mem_copy(pData, &m_InputData, sizeof(m_InputData)); + return sizeof(m_InputData); } -void CONTROLS::on_render() +void CControls::OnRender() { // update target pos - if(gameclient.snap.gameobj && !(gameclient.snap.gameobj->paused || gameclient.snap.spectate)) - target_pos = gameclient.local_character_pos + mouse_pos; + if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Paused || m_pClient->m_Snap.m_Spectate)) + m_TargetPos = m_pClient->m_LocalCharacterPos + m_MousePos; } -bool CONTROLS::on_mousemove(float x, float y) +bool CControls::OnMouseMove(float x, float y) { - if(gameclient.snap.gameobj && gameclient.snap.gameobj->paused) + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Paused) return false; - mouse_pos += vec2(x, y); // TODO: ugly + m_MousePos += vec2(x, y); // TODO: ugly // - float camera_max_distance = 200.0f; - float follow_factor = config.cl_mouse_followfactor/100.0f; - float deadzone = config.cl_mouse_deadzone; - float mouse_max = min(camera_max_distance/follow_factor + deadzone, (float)config.cl_mouse_max_distance); + float CameraMaxDistance = 200.0f; + float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; + float DeadZone = g_Config.m_ClMouseDeadzone; + float MouseMax = min(CameraMaxDistance/FollowFactor + DeadZone, (float)g_Config.m_ClMouseMaxDistance); //vec2 camera_offset(0, 0); - if(gameclient.snap.spectate) + if(m_pClient->m_Snap.m_Spectate) { - if(mouse_pos.x < 200.0f) mouse_pos.x = 200.0f; - if(mouse_pos.y < 200.0f) mouse_pos.y = 200.0f; - if(mouse_pos.x > col_width()*32-200.0f) mouse_pos.x = col_width()*32-200.0f; - if(mouse_pos.y > col_height()*32-200.0f) mouse_pos.y = col_height()*32-200.0f; + if(m_MousePos.x < 200.0f) m_MousePos.x = 200.0f; + if(m_MousePos.y < 200.0f) m_MousePos.y = 200.0f; + if(m_MousePos.x > Collision()->GetWidth()*32-200.0f) m_MousePos.x = Collision()->GetWidth()*32-200.0f; + if(m_MousePos.y > Collision()->GetHeight()*32-200.0f) m_MousePos.y = Collision()->GetHeight()*32-200.0f; - target_pos = mouse_pos; + m_TargetPos = m_MousePos; } else { - float l = length(mouse_pos); + float l = length(m_MousePos); - if(l > mouse_max) + if(l > MouseMax) { - mouse_pos = normalize(mouse_pos)*mouse_max; - l = mouse_max; + m_MousePos = normalize(m_MousePos)*MouseMax; + l = MouseMax; } //float offset_amount = max(l-deadzone, 0.0f) * follow_factor; diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h new file mode 100644 index 00000000..7453d5d7 --- /dev/null +++ b/src/game/client/components/controls.h @@ -0,0 +1,25 @@ +#ifndef GAME_CLIENT_COMPONENTS_CONTROLS_H +#define GAME_CLIENT_COMPONENTS_CONTROLS_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CControls : public CComponent +{ +public: + vec2 m_MousePos; + vec2 m_TargetPos; + + CNetObj_PlayerInput m_InputData; + int m_InputDirectionLeft; + int m_InputDirectionRight; + + CControls(); + + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); + virtual bool OnMouseMove(float x, float y); + virtual void OnConsoleInit(); + + int SnapInput(int *pData); +}; +#endif diff --git a/src/game/client/components/controls.hpp b/src/game/client/components/controls.hpp deleted file mode 100644 index e33d24f5..00000000 --- a/src/game/client/components/controls.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class CONTROLS : public COMPONENT -{ -public: - vec2 mouse_pos; - vec2 target_pos; - - NETOBJ_PLAYER_INPUT input_data; - int input_direction_left; - int input_direction_right; - - CONTROLS(); - - virtual void on_render(); - virtual void on_message(int msg, void *rawmsg); - virtual bool on_mousemove(float x, float y); - virtual void on_console_init(); - - int snapinput(int *data); -}; diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index 7f1991dc..8dfbf022 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -1,65 +1,64 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/graphics.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/gamecore.hpp> // get_angle -#include <game/client/ui.hpp> -#include <game/client/render.hpp> -#include "damageind.hpp" +#include <game/gamecore.h> // get_angle +#include <game/client/ui.h> +#include <game/client/render.h> +#include "damageind.h" -DAMAGEIND::DAMAGEIND() +CDamageInd::CDamageInd() { - lastupdate = 0; - num_items = 0; + m_Lastupdate = 0; + m_NumItems = 0; } -DAMAGEIND::ITEM *DAMAGEIND::create_i() +CDamageInd::CItem *CDamageInd::CreateI() { - if (num_items < MAX_ITEMS) + if (m_NumItems < MAX_ITEMS) { - ITEM *p = &items[num_items]; - num_items++; + CItem *p = &m_aItems[m_NumItems]; + m_NumItems++; return p; } return 0; } -void DAMAGEIND::destroy_i(DAMAGEIND::ITEM *i) +void CDamageInd::DestroyI(CDamageInd::CItem *i) { - num_items--; - *i = items[num_items]; + m_NumItems--; + *i = m_aItems[m_NumItems]; } -void DAMAGEIND::create(vec2 pos, vec2 dir) +void CDamageInd::Create(vec2 Pos, vec2 Dir) { - ITEM *i = create_i(); + CItem *i = CreateI(); if (i) { - i->pos = pos; - i->life = 0.75f; - i->dir = dir*-1; - i->startangle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi; + i->m_Pos = Pos; + i->m_Life = 0.75f; + i->m_Dir = Dir*-1; + i->m_StartAngle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi; } } -void DAMAGEIND::on_render() +void CDamageInd::OnRender() { - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - for(int i = 0; i < num_items;) + for(int i = 0; i < m_NumItems;) { - vec2 pos = mix(items[i].pos+items[i].dir*75.0f, items[i].pos, clamp((items[i].life-0.60f)/0.15f, 0.0f, 1.0f)); + vec2 Pos = mix(m_aItems[i].m_Pos+m_aItems[i].m_Dir*75.0f, m_aItems[i].m_Pos, clamp((m_aItems[i].m_Life-0.60f)/0.15f, 0.0f, 1.0f)); - items[i].life -= client_frametime(); - if(items[i].life < 0.0f) - destroy_i(&items[i]); + m_aItems[i].m_Life -= Client()->FrameTime(); + if(m_aItems[i].m_Life < 0.0f) + DestroyI(&m_aItems[i]); else { - Graphics()->SetColor(1.0f,1.0f,1.0f, items[i].life/0.1f); - Graphics()->QuadsSetRotation(items[i].startangle + items[i].life * 2.0f); - RenderTools()->select_sprite(SPRITE_STAR1); - RenderTools()->draw_sprite(pos.x, pos.y, 48.0f); + Graphics()->SetColor(1.0f,1.0f,1.0f, m_aItems[i].m_Life/0.1f); + Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + m_aItems[i].m_Life * 2.0f); + RenderTools()->SelectSprite(SPRITE_STAR1); + RenderTools()->DrawSprite(Pos.x, Pos.y, 48.0f); i++; } } diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h new file mode 100644 index 00000000..b6e0bb47 --- /dev/null +++ b/src/game/client/components/damageind.h @@ -0,0 +1,34 @@ +#ifndef GAME_CLIENT_COMPONENTS_DAMAGEIND_H +#define GAME_CLIENT_COMPONENTS_DAMAGEIND_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CDamageInd : public CComponent +{ + int64 m_Lastupdate; + struct CItem + { + vec2 m_Pos; + vec2 m_Dir; + float m_Life; + float m_StartAngle; + }; + + enum + { + MAX_ITEMS=64, + }; + + CItem m_aItems[MAX_ITEMS]; + int m_NumItems; + + CItem *CreateI(); + void DestroyI(CItem *i); + +public: + CDamageInd(); + + void Create(vec2 Pos, vec2 Dir); + virtual void OnRender(); +}; +#endif diff --git a/src/game/client/components/damageind.hpp b/src/game/client/components/damageind.hpp deleted file mode 100644 index c74af9ca..00000000 --- a/src/game/client/components/damageind.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class DAMAGEIND : public COMPONENT -{ - int64 lastupdate; - struct ITEM - { - vec2 pos; - vec2 dir; - float life; - float startangle; - }; - - enum - { - MAX_ITEMS=64, - }; - - ITEM items[MAX_ITEMS]; - int num_items; - - ITEM *create_i(); - void destroy_i(ITEM *i); - -public: - DAMAGEIND(); - - void create(vec2 pos, vec2 dir); - virtual void on_render(); -}; diff --git a/src/game/client/components/debughud.cpp b/src/game/client/components/debughud.cpp index c7cc559b..0fa004cb 100644 --- a/src/game/client/components/debughud.cpp +++ b/src/game/client/components/debughud.cpp @@ -1,27 +1,23 @@ -#include <memory.h> // memcmp +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/textrender.h> -extern "C" { - #include <engine/e_config.h> -} - -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/layers.hpp> +#include <game/layers.h> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include <game/client/render.hpp> +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include <game/client/render.h> -//#include "controls.hpp" -//#include "camera.hpp" -#include "debughud.hpp" +//#include "controls.h" +//#include "camera.h" +#include "debughud.h" -void DEBUGHUD::render_netcorrections() +void CDebugHud::RenderNetCorrections() { - if(!config.debug || !gameclient.snap.local_character || !gameclient.snap.local_prev_character) + if(!g_Config.m_Debug || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) return; Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); @@ -29,7 +25,8 @@ void DEBUGHUD::render_netcorrections() /*float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y), vec2(netobjects.local_character->x, netobjects.local_character->y));*/ - float velspeed = length(vec2(gameclient.snap.local_character->vx/256.0f, gameclient.snap.local_character->vy/256.0f))*50; +/* + float velspeed = length(vec2(gameclient.snap.local_character->m_VelX/256.0f, gameclient.snap.local_character->m_VelY/256.0f))*50; float ramp = velocity_ramp(velspeed, gameclient.tuning.velramp_start, gameclient.tuning.velramp_range, gameclient.tuning.velramp_curvature); @@ -37,77 +34,79 @@ void DEBUGHUD::render_netcorrections() str_format(buf, sizeof(buf), "%.0f\n%.0f\n%.2f\n%d %s\n%d %d", velspeed, velspeed*ramp, ramp, netobj_num_corrections(), netobj_corrected_on(), - gameclient.snap.local_character->x, - gameclient.snap.local_character->y + gameclient.snap.local_character->m_X, + gameclient.snap.local_character->m_Y ); - gfx_text(0, 150, 50, 12, buf, -1); + TextRender()->Text(0, 150, 50, 12, buf, -1);*/ } -void DEBUGHUD::render_tuning() +void CDebugHud::RenderTuning() { // render tuning debugging - if(!config.dbg_tuning) + if(!g_Config.m_DbgTuning) return; - TUNING_PARAMS standard_tuning; + CTuningParams StandardTuning; Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); float y = 50.0f; - int count = 0; - for(int i = 0; i < gameclient.tuning.num(); i++) + int Count = 0; + for(int i = 0; i < m_pClient->m_Tuning.Num(); i++) { - char buf[128]; - float current, standard; - gameclient.tuning.get(i, ¤t); - standard_tuning.get(i, &standard); + char aBuf[128]; + float Current, Standard; + m_pClient->m_Tuning.Get(i, &Current); + StandardTuning.Get(i, &Standard); - if(standard == current) - gfx_text_color(1,1,1,1.0f); + if(Standard == Current) + TextRender()->TextColor(1,1,1,1.0f); else - gfx_text_color(1,0.25f,0.25f,1.0f); + TextRender()->TextColor(1,0.25f,0.25f,1.0f); float w; float x = 5.0f; - str_format(buf, sizeof(buf), "%.2f", standard); + str_format(aBuf, sizeof(aBuf), "%.2f", Standard); x += 20.0f; - w = gfx_text_width(0, 5, buf, -1); - gfx_text(0x0, x-w, y+count*6, 5, buf, -1); + w = TextRender()->TextWidth(0, 5, aBuf, -1); + TextRender()->Text(0x0, x-w, y+Count*6, 5, aBuf, -1); - str_format(buf, sizeof(buf), "%.2f", current); + str_format(aBuf, sizeof(aBuf), "%.2f", Current); x += 20.0f; - w = gfx_text_width(0, 5, buf, -1); - gfx_text(0x0, x-w, y+count*6, 5, buf, -1); + w = TextRender()->TextWidth(0, 5, aBuf, -1); + TextRender()->Text(0x0, x-w, y+Count*6, 5, aBuf, -1); x += 5.0f; - gfx_text(0x0, x, y+count*6, 5, gameclient.tuning.names[i], -1); + TextRender()->Text(0x0, x, y+Count*6, 5, m_pClient->m_Tuning.m_apNames[i], -1); - count++; + Count++; } - y = y+count*6; + y = y+Count*6; Graphics()->TextureSet(-1); Graphics()->BlendNormal(); Graphics()->LinesBegin(); - float height = 50.0f; + float Height = 50.0f; float pv = 1; + IGraphics::CLineItem Array[100]; for(int i = 0; i < 100; i++) { - float speed = i/100.0f * 3000; - float ramp = velocity_ramp(speed, gameclient.tuning.velramp_start, gameclient.tuning.velramp_range, gameclient.tuning.velramp_curvature); - float rampedspeed = (speed * ramp)/1000.0f; - Graphics()->LinesDraw((i-1)*2, y+height-pv*height, i*2, y+height-rampedspeed*height); + float Speed = i/100.0f * 3000; + float Ramp = VelocityRamp(Speed, m_pClient->m_Tuning.m_VelrampStart, m_pClient->m_Tuning.m_VelrampRange, m_pClient->m_Tuning.m_VelrampCurvature); + float RampedSpeed = (Speed * Ramp)/1000.0f; + Array[i] = IGraphics::CLineItem((i-1)*2, y+Height-pv*Height, i*2, y+Height-RampedSpeed*Height); //Graphics()->LinesDraw((i-1)*2, 200, i*2, 200); - pv = rampedspeed; + pv = RampedSpeed; } + Graphics()->LinesDraw(Array, 100); Graphics()->LinesEnd(); - gfx_text_color(1,1,1,1); + TextRender()->TextColor(1,1,1,1); } -void DEBUGHUD::on_render() +void CDebugHud::OnRender() { - render_tuning(); - render_netcorrections(); + RenderTuning(); + RenderNetCorrections(); } diff --git a/src/game/client/components/debughud.h b/src/game/client/components/debughud.h new file mode 100644 index 00000000..ae1c17ef --- /dev/null +++ b/src/game/client/components/debughud.h @@ -0,0 +1,13 @@ +#ifndef GAME_CLIENT_COMPONENTS_DEBUGHUD_H +#define GAME_CLIENT_COMPONENTS_DEBUGHUD_H +#include <game/client/component.h> + +class CDebugHud : public CComponent +{ + void RenderNetCorrections(); + void RenderTuning(); +public: + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/debughud.hpp b/src/game/client/components/debughud.hpp deleted file mode 100644 index 473b2ce2..00000000 --- a/src/game/client/components/debughud.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#include <game/client/component.hpp> - -class DEBUGHUD : public COMPONENT -{ - void render_netcorrections(); - void render_tuning(); -public: - virtual void on_render(); -}; - diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index c9c47a8d..91cea107 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -1,183 +1,181 @@ -#include <engine/e_client_interface.h> -//#include <gc_client.hpp> -#include <game/generated/gc_data.hpp> +#include <game/generated/client_data.h> -#include <game/client/components/particles.hpp> -#include <game/client/components/skins.hpp> -#include <game/client/components/flow.hpp> -#include <game/client/components/damageind.hpp> -#include <game/client/components/sounds.hpp> -#include <game/client/gameclient.hpp> +#include <game/client/components/particles.h> +#include <game/client/components/skins.h> +#include <game/client/components/flow.h> +#include <game/client/components/damageind.h> +#include <game/client/components/sounds.h> +#include <game/client/gameclient.h> -#include "effects.hpp" +#include "effects.h" -inline vec2 random_dir() { return normalize(vec2(frandom()-0.5f, frandom()-0.5f)); } +inline vec2 RandomDir() { return normalize(vec2(frandom()-0.5f, frandom()-0.5f)); } -EFFECTS::EFFECTS() +CEffects::CEffects() { - add_50hz = false; - add_100hz = false; + m_Add50hz = false; + m_Add100hz = false; } -void EFFECTS::air_jump(vec2 pos) +void CEffects::AirJump(vec2 Pos) { - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_AIRJUMP; - p.pos = pos + vec2(-6.0f, 16.0f); - p.vel = vec2(0, -200); - p.life_span = 0.5f; - p.start_size = 48.0f; - p.end_size = 0; - p.rot = frandom()*pi*2; - p.rotspeed = pi*2; - p.gravity = 500; - p.friction = 0.7f; - p.flow_affected = 0.0f; - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_AIRJUMP; + p.m_Pos = Pos + vec2(-6.0f, 16.0f); + p.m_Vel = vec2(0, -200); + p.m_LifeSpan = 0.5f; + p.m_StartSize = 48.0f; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + p.m_Rotspeed = pi*2; + p.m_Gravity = 500; + p.m_Friction = 0.7f; + p.m_FlowAffected = 0.0f; + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); - p.pos = pos + vec2(6.0f, 16.0f); - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + p.m_Pos = Pos + vec2(6.0f, 16.0f); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); - gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos); + m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, Pos); } -void EFFECTS::damage_indicator(vec2 pos, vec2 dir) +void CEffects::DamageIndicator(vec2 Pos, vec2 Dir) { - gameclient.damageind->create(pos, dir); + m_pClient->m_pDamageind->Create(Pos, Dir); } -void EFFECTS::powerupshine(vec2 pos, vec2 size) +void CEffects::PowerupShine(vec2 Pos, vec2 size) { - if(!add_50hz) + if(!m_Add50hz) return; - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SLICE; - p.pos = pos + vec2((frandom()-0.5f)*size.x, (frandom()-0.5f)*size.y); - p.vel = vec2(0, 0); - p.life_span = 0.5f; - p.start_size = 16.0f; - p.end_size = 0; - p.rot = frandom()*pi*2; - p.rotspeed = pi*2; - p.gravity = 500; - p.friction = 0.9f; - p.flow_affected = 0.0f; - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SLICE; + p.m_Pos = Pos + vec2((frandom()-0.5f)*size.x, (frandom()-0.5f)*size.y); + p.m_Vel = vec2(0, 0); + p.m_LifeSpan = 0.5f; + p.m_StartSize = 16.0f; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + p.m_Rotspeed = pi*2; + p.m_Gravity = 500; + p.m_Friction = 0.9f; + p.m_FlowAffected = 0.0f; + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } -void EFFECTS::smoketrail(vec2 pos, vec2 vel) +void CEffects::SmokeTrail(vec2 Pos, vec2 Vel) { - if(!add_50hz) + if(!m_Add50hz) return; - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SMOKE; - p.pos = pos; - p.vel = vel + random_dir()*50.0f; - p.life_span = 0.5f + frandom()*0.5f; - p.start_size = 12.0f + frandom()*8; - p.end_size = 0; - p.friction = 0.7; - p.gravity = frandom()*-500.0f; - gameclient.particles->add(PARTICLES::GROUP_PROJECTILE_TRAIL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SMOKE; + p.m_Pos = Pos; + p.m_Vel = Vel + RandomDir()*50.0f; + p.m_LifeSpan = 0.5f + frandom()*0.5f; + p.m_StartSize = 12.0f + frandom()*8; + p.m_EndSize = 0; + p.m_Friction = 0.7; + p.m_Gravity = frandom()*-500.0f; + m_pClient->m_pParticles->Add(CParticles::GROUP_PROJECTILE_TRAIL, &p); } -void EFFECTS::skidtrail(vec2 pos, vec2 vel) +void CEffects::SkidTrail(vec2 Pos, vec2 Vel) { - if(!add_100hz) + if(!m_Add100hz) return; - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SMOKE; - p.pos = pos; - p.vel = vel + random_dir()*50.0f; - p.life_span = 0.5f + frandom()*0.5f; - p.start_size = 24.0f + frandom()*12; - p.end_size = 0; - p.friction = 0.7f; - p.gravity = frandom()*-500.0f; - p.color = vec4(0.75f,0.75f,0.75f,1.0f); - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SMOKE; + p.m_Pos = Pos; + p.m_Vel = Vel + RandomDir()*50.0f; + p.m_LifeSpan = 0.5f + frandom()*0.5f; + p.m_StartSize = 24.0f + frandom()*12; + p.m_EndSize = 0; + p.m_Friction = 0.7f; + p.m_Gravity = frandom()*-500.0f; + p.m_Color = vec4(0.75f,0.75f,0.75f,1.0f); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } -void EFFECTS::bullettrail(vec2 pos) +void CEffects::BulletTrail(vec2 Pos) { - if(!add_100hz) + if(!m_Add100hz) return; - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_BALL; - p.pos = pos; - p.life_span = 0.25f + frandom()*0.25f; - p.start_size = 8.0f; - p.end_size = 0; - p.friction = 0.7f; - gameclient.particles->add(PARTICLES::GROUP_PROJECTILE_TRAIL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_BALL; + p.m_Pos = Pos; + p.m_LifeSpan = 0.25f + frandom()*0.25f; + p.m_StartSize = 8.0f; + p.m_EndSize = 0; + p.m_Friction = 0.7f; + m_pClient->m_pParticles->Add(CParticles::GROUP_PROJECTILE_TRAIL, &p); } -void EFFECTS::playerspawn(vec2 pos) +void CEffects::PlayerSpawn(vec2 Pos) { for(int i = 0; i < 32; i++) { - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SHELL; - p.pos = pos; - p.vel = random_dir() * (pow(frandom(), 3)*600.0f); - p.life_span = 0.3f + frandom()*0.3f; - p.start_size = 64.0f + frandom()*32; - p.end_size = 0; - p.rot = frandom()*pi*2; - p.rotspeed = frandom(); - p.gravity = frandom()*-400.0f; - p.friction = 0.7f; - p.color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f); - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SHELL; + p.m_Pos = Pos; + p.m_Vel = RandomDir() * (powf(frandom(), 3)*600.0f); + p.m_LifeSpan = 0.3f + frandom()*0.3f; + p.m_StartSize = 64.0f + frandom()*32; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + p.m_Rotspeed = frandom(); + p.m_Gravity = frandom()*-400.0f; + p.m_Friction = 0.7f; + p.m_Color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } - gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, pos); + m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, Pos); } -void EFFECTS::playerdeath(vec2 pos, int cid) +void CEffects::PlayerDeath(vec2 Pos, int Cid) { - vec3 blood_color(1.0f,1.0f,1.0f); + vec3 BloodColor(1.0f,1.0f,1.0f); - if(cid >= 0) + if(Cid >= 0) { - const SKINS::SKIN *s = gameclient.skins->get(gameclient.clients[cid].skin_id); + const CSkins::CSkin *s = m_pClient->m_pSkins->Get(m_pClient->m_aClients[Cid].m_SkinId); if(s) - blood_color = s->blood_color; + BloodColor = s->m_BloodColor; } for(int i = 0; i < 64; i++) { - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SPLAT01 + (rand()%3); - p.pos = pos; - p.vel = random_dir() * ((frandom()+0.1f)*900.0f); - p.life_span = 0.3f + frandom()*0.3f; - p.start_size = 24.0f + frandom()*16; - p.end_size = 0; - p.rot = frandom()*pi*2; - p.rotspeed = (frandom()-0.5f) * pi; - p.gravity = 800.0f; - p.friction = 0.8f; - vec3 c = blood_color * (0.75f + frandom()*0.25f); - p.color = vec4(c.r, c.g, c.b, 0.75f); - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SPLAT01 + (rand()%3); + p.m_Pos = Pos; + p.m_Vel = RandomDir() * ((frandom()+0.1f)*900.0f); + p.m_LifeSpan = 0.3f + frandom()*0.3f; + p.m_StartSize = 24.0f + frandom()*16; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + p.m_Rotspeed = (frandom()-0.5f) * pi; + p.m_Gravity = 800.0f; + p.m_Friction = 0.8f; + vec3 c = BloodColor * (0.75f + frandom()*0.25f); + p.m_Color = vec4(c.r, c.g, c.b, 0.75f); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } } -void EFFECTS::explosion(vec2 pos) +void CEffects::Explosion(vec2 Pos) { // add to flow for(int y = -8; y <= 8; y++) @@ -187,75 +185,75 @@ void EFFECTS::explosion(vec2 pos) continue; float a = 1 - (length(vec2(x,y)) / length(vec2(8,8))); - gameclient.flow->add(pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f); + m_pClient->m_pFlow->Add(Pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f); } // add the explosion - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_EXPL01; - p.pos = pos; - p.life_span = 0.4f; - p.start_size = 150.0f; - p.end_size = 0; - p.rot = frandom()*pi*2; - gameclient.particles->add(PARTICLES::GROUP_EXPLOSIONS, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_EXPL01; + p.m_Pos = Pos; + p.m_LifeSpan = 0.4f; + p.m_StartSize = 150.0f; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); // add the smoke for(int i = 0; i < 24; i++) { - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_SMOKE; - p.pos = pos; - p.vel = random_dir() * ((1.0f + frandom()*0.2f) * 1000.0f); - p.life_span = 0.5f + frandom()*0.4f; - p.start_size = 32.0f + frandom()*8; - p.end_size = 0; - p.gravity = frandom()*-800.0f; - p.friction = 0.4f; - p.color = mix(vec4(0.75f,0.75f,0.75f,1.0f), vec4(0.5f,0.5f,0.5f,1.0f), frandom()); - gameclient.particles->add(PARTICLES::GROUP_GENERAL, &p); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_SMOKE; + p.m_Pos = Pos; + p.m_Vel = RandomDir() * ((1.0f + frandom()*0.2f) * 1000.0f); + p.m_LifeSpan = 0.5f + frandom()*0.4f; + p.m_StartSize = 32.0f + frandom()*8; + p.m_EndSize = 0; + p.m_Gravity = frandom()*-800.0f; + p.m_Friction = 0.4f; + p.m_Color = mix(vec4(0.75f,0.75f,0.75f,1.0f), vec4(0.5f,0.5f,0.5f,1.0f), frandom()); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } } -void EFFECTS::hammerhit(vec2 pos) +void CEffects::HammerHit(vec2 Pos) { // add the explosion - PARTICLE p; - p.set_default(); - p.spr = SPRITE_PART_EXPL01; - p.pos = pos; - p.life_span = 0.4f; - p.start_size = 150.0f; - p.end_size = 0; - p.rot = frandom()*pi*2; - gameclient.particles->add(PARTICLES::GROUP_EXPLOSIONS, &p); - gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, pos); + CParticle p; + p.SetDefault(); + p.m_Spr = SPRITE_PART_EXPL01; + p.m_Pos = Pos; + p.m_LifeSpan = 0.4f; + p.m_StartSize = 150.0f; + p.m_EndSize = 0; + p.m_Rot = frandom()*pi*2; + m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); + m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, Pos); } -void EFFECTS::on_render() +void CEffects::OnRender() { - static int64 last_update_100hz = 0; - static int64 last_update_50hz = 0; + static int64 LastUpdate100hz = 0; + static int64 LastUpdate50hz = 0; - if(time_get()-last_update_100hz > time_freq()/100) + if(time_get()-LastUpdate100hz > time_freq()/100) { - add_100hz = true; - last_update_100hz = time_get(); + m_Add100hz = true; + LastUpdate100hz = time_get(); } else - add_100hz = false; + m_Add100hz = false; - if(time_get()-last_update_50hz > time_freq()/100) + if(time_get()-LastUpdate50hz > time_freq()/100) { - add_50hz = true; - last_update_50hz = time_get(); + m_Add50hz = true; + LastUpdate50hz = time_get(); } else - add_50hz = false; + m_Add50hz = false; - if(add_50hz) - gameclient.flow->update(); + if(m_Add50hz) + m_pClient->m_pFlow->Update(); } diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h new file mode 100644 index 00000000..e8345500 --- /dev/null +++ b/src/game/client/components/effects.h @@ -0,0 +1,27 @@ +#ifndef GAME_CLIENT_COMPONENTS_EFFECTS_H +#define GAME_CLIENT_COMPONENTS_EFFECTS_H +#include <game/client/component.h> + +class CEffects : public CComponent +{ + bool m_Add50hz; + bool m_Add100hz; +public: + CEffects(); + + virtual void OnRender(); + + void BulletTrail(vec2 Pos); + void SmokeTrail(vec2 Pos, vec2 Vel); + void SkidTrail(vec2 Pos, vec2 Vel); + void Explosion(vec2 Pos); + void HammerHit(vec2 Pos); + void AirJump(vec2 Pos); + void DamageIndicator(vec2 Pos, vec2 Dir); + void PlayerSpawn(vec2 Pos); + void PlayerDeath(vec2 Pos, int ClientId); + void PowerupShine(vec2 Pos, vec2 Size); + + void Update(); +}; +#endif diff --git a/src/game/client/components/effects.hpp b/src/game/client/components/effects.hpp deleted file mode 100644 index 8574bf60..00000000 --- a/src/game/client/components/effects.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include <game/client/component.hpp> - -class EFFECTS : public COMPONENT -{ - bool add_50hz; - bool add_100hz; -public: - EFFECTS(); - - virtual void on_render(); - - void bullettrail(vec2 pos); - void smoketrail(vec2 pos, vec2 vel); - void skidtrail(vec2 pos, vec2 vel); - void explosion(vec2 pos); - void hammerhit(vec2 pos); - void air_jump(vec2 pos); - void damage_indicator(vec2 pos, vec2 dir); - void playerspawn(vec2 pos); - void playerdeath(vec2 pos, int cid); - void powerupshine(vec2 pos, vec2 size); - - void update(); -}; diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index 8001a306..6d03f88d 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -1,157 +1,161 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> - -#include <game/gamecore.hpp> // get_angle -#include <game/client/gameclient.hpp> -#include <game/client/ui.hpp> -#include <game/client/render.hpp> -#include "emoticon.hpp" - -EMOTICON::EMOTICON() +#include <engine/graphics.h> +#include <engine/shared/config.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> + +#include <game/gamecore.h> // get_angle +#include <game/client/gameclient.h> +#include <game/client/ui.h> +#include <game/client/render.h> +#include "emoticon.h" + +CEmoticon::CEmoticon() { - on_reset(); + OnReset(); } -void EMOTICON::con_key_emoticon(void *result, void *user_data) +void CEmoticon::ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData) { - ((EMOTICON *)user_data)->active = console_arg_int(result, 0) != 0; + ((CEmoticon *)pUserData)->m_Active = pResult->GetInteger(0) != 0; } -void EMOTICON::con_emote(void *result, void *user_data) +void CEmoticon::ConEmote(IConsole::IResult *pResult, void *pUserData) { - ((EMOTICON *)user_data)->emote(console_arg_int(result, 0)); + ((CEmoticon *)pUserData)->Emote(pResult->GetInteger(0)); } -void EMOTICON::on_console_init() +void CEmoticon::OnConsoleInit() { - MACRO_REGISTER_COMMAND("+emote", "", CFGFLAG_CLIENT, con_key_emoticon, this, "Open emote selector"); - MACRO_REGISTER_COMMAND("emote", "i", CFGFLAG_CLIENT, con_emote, this, "Use emote"); + Console()->Register("+emote", "", CFGFLAG_CLIENT, ConKeyEmoticon, this, "Open emote selector"); + Console()->Register("emote", "i", CFGFLAG_CLIENT, ConEmote, this, "Use emote"); } -void EMOTICON::on_reset() +void CEmoticon::OnReset() { - was_active = false; - active = false; - selected_emote = -1; + m_WasActive = false; + m_Active = false; + m_SelectedEmote = -1; } -void EMOTICON::on_message(int msgtype, void *rawmsg) +void CEmoticon::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_EMOTICON) - { - NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg; - gameclient.clients[msg->cid].emoticon = msg->emoticon; - gameclient.clients[msg->cid].emoticon_start = client_tick(); - } } -bool EMOTICON::on_mousemove(float x, float y) +bool CEmoticon::OnMouseMove(float x, float y) { - if(!active) + if(!m_Active) return false; - selector_mouse += vec2(x,y); + m_SelectorMouse += vec2(x,y); return true; } -void EMOTICON::draw_circle(float x, float y, float r, int segments) +void CEmoticon::DrawCircle(float x, float y, float r, int Segments) { - float f_segments = (float)segments; - for(int i = 0; i < segments; i+=2) + IGraphics::CFreeformItem Array[32]; + int NumItems = 0; + float FSegments = (float)Segments; + for(int i = 0; i < Segments; i+=2) { - float a1 = i/f_segments * 2*pi; - float a2 = (i+1)/f_segments * 2*pi; - float a3 = (i+2)/f_segments * 2*pi; - float ca1 = cosf(a1); - float ca2 = cosf(a2); - float ca3 = cosf(a3); - float sa1 = sinf(a1); - float sa2 = sinf(a2); - float sa3 = sinf(a3); - - client->Graphics()->QuadsDrawFreeform( + float a1 = i/FSegments * 2*pi; + float a2 = (i+1)/FSegments * 2*pi; + float a3 = (i+2)/FSegments * 2*pi; + float Ca1 = cosf(a1); + float Ca2 = cosf(a2); + float Ca3 = cosf(a3); + float Sa1 = sinf(a1); + float Sa2 = sinf(a2); + float Sa3 = sinf(a3); + + Array[NumItems++] = IGraphics::CFreeformItem( x, y, - x+ca1*r, y+sa1*r, - x+ca3*r, y+sa3*r, - x+ca2*r, y+sa2*r); + x+Ca1*r, y+Sa1*r, + x+Ca3*r, y+Sa3*r, + x+Ca2*r, y+Sa2*r); + if(NumItems == 32) + { + m_pClient->Graphics()->QuadsDrawFreeform(Array, 32); + NumItems = 0; + } } + if(NumItems) + m_pClient->Graphics()->QuadsDrawFreeform(Array, NumItems); } -void EMOTICON::on_render() +void CEmoticon::OnRender() { - if(!active) + if(!m_Active) { - if(was_active && selected_emote != -1) - emote(selected_emote); - was_active = false; + if(m_WasActive && m_SelectedEmote != -1) + Emote(m_SelectedEmote); + m_WasActive = false; return; } - was_active = true; + m_WasActive = true; int x, y; - inp_mouse_relative(&x, &y); + Input()->MouseRelative(&x, &y); - selector_mouse.x += x; - selector_mouse.y += y; + m_SelectorMouse.x += x; + m_SelectorMouse.y += y; - if (length(selector_mouse) > 140) - selector_mouse = normalize(selector_mouse) * 140; + if (length(m_SelectorMouse) > 140) + m_SelectorMouse = normalize(m_SelectorMouse) * 140; - float selected_angle = get_angle(selector_mouse) + 2*pi/24; - if (selected_angle < 0) - selected_angle += 2*pi; + float SelectedAngle = GetAngle(m_SelectorMouse) + 2*pi/24; + if (SelectedAngle < 0) + SelectedAngle += 2*pi; - if (length(selector_mouse) > 100) - selected_emote = (int)(selected_angle / (2*pi) * 12.0f); + if (length(m_SelectorMouse) > 100) + m_SelectedEmote = (int)(SelectedAngle / (2*pi) * 12.0f); - CUIRect screen = *UI()->Screen(); + CUIRect Screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); - draw_circle(screen.w/2, screen.h/2, 160, 64); + DrawCircle(Screen.w/2, Screen.h/2, 160, 64); Graphics()->QuadsEnd(); - Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); for (int i = 0; i < 12; i++) { - float angle = 2*pi*i/12.0; - if (angle > pi) - angle -= 2*pi; + float Angle = 2*pi*i/12.0; + if (Angle > pi) + Angle -= 2*pi; - bool selected = selected_emote == i; + bool Selected = m_SelectedEmote == i; - float size = selected ? 96 : 64; + float Size = Selected ? 96 : 64; - float nudge_x = 120 * cos(angle); - float nudge_y = 120 * sin(angle); - RenderTools()->select_sprite(SPRITE_OOP + i); - Graphics()->QuadsDraw(screen.w/2 + nudge_x, screen.h/2 + nudge_y, size, size); + float NudgeX = 120 * cosf(Angle); + float NudgeY = 120 * sinf(Angle); + RenderTools()->SelectSprite(SPRITE_OOP + i); + IGraphics::CQuadItem QuadItem(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY, Size, Size); + Graphics()->QuadsDraw(&QuadItem, 1); } Graphics()->QuadsEnd(); - Graphics()->TextureSet(data->images[IMAGE_CURSOR].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); - Graphics()->QuadsDrawTL(selector_mouse.x+screen.w/2,selector_mouse.y+screen.h/2,24,24); + IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } -void EMOTICON::emote(int emoticon) +void CEmoticon::Emote(int Emoticon) { - NETMSG_CL_EMOTICON msg; - msg.emoticon = emoticon; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_Emoticon Msg; + Msg.m_Emoticon = Emoticon; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } diff --git a/src/game/client/components/emoticon.h b/src/game/client/components/emoticon.h new file mode 100644 index 00000000..e10b57da --- /dev/null +++ b/src/game/client/components/emoticon.h @@ -0,0 +1,31 @@ +#ifndef GAME_CLIENT_COMPONENTS_EMOTICON_H +#define GAME_CLIENT_COMPONENTS_EMOTICON_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CEmoticon : public CComponent +{ + void DrawCircle(float x, float y, float r, int Segments); + + bool m_WasActive; + bool m_Active; + + vec2 m_SelectorMouse; + int m_SelectedEmote; + + static void ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData); + static void ConEmote(IConsole::IResult *pResult, void *pUserData); + +public: + CEmoticon(); + + virtual void OnReset(); + virtual void OnConsoleInit(); + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); + virtual bool OnMouseMove(float x, float y); + + void Emote(int Emoticon); +}; + +#endif diff --git a/src/game/client/components/emoticon.hpp b/src/game/client/components/emoticon.hpp deleted file mode 100644 index 446b4b00..00000000 --- a/src/game/client/components/emoticon.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class EMOTICON : public COMPONENT -{ - void draw_circle(float x, float y, float r, int segments); - - bool was_active; - bool active; - - vec2 selector_mouse; - int selected_emote; - - static void con_key_emoticon(void *result, void *user_data); - static void con_emote(void *result, void *user_data); - -public: - EMOTICON(); - - virtual void on_reset(); - virtual void on_console_init(); - virtual void on_render(); - virtual void on_message(int msgtype, void *rawmsg); - virtual bool on_mousemove(float x, float y); - - void emote(int emoticon); -}; - diff --git a/src/game/client/components/flow.cpp b/src/game/client/components/flow.cpp index 9ecd4b5c..d2ba704c 100644 --- a/src/game/client/components/flow.cpp +++ b/src/game/client/components/flow.cpp @@ -1,85 +1,94 @@ -#include <engine/client/graphics.h> -#include <game/mapitems.hpp> -#include <game/layers.hpp> -#include "flow.hpp" +#include <engine/graphics.h> +#include <game/mapitems.h> +#include <game/layers.h> +#include "flow.h" -FLOW::FLOW() +CFlow::CFlow() { - cells = 0; - height = 0; - width = 0; - spacing = 16; + m_pCells = 0; + m_Height = 0; + m_Width = 0; + m_Spacing = 16; } -void FLOW::dbg_render() +void CFlow::DbgRender() { - if(!cells) + if(!m_pCells) return; + IGraphics::CLineItem Array[1024]; + int NumItems = 0; Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) { - vec2 pos(x*spacing, y*spacing); - vec2 vel = cells[y*width+x].vel * 0.01f; - Graphics()->LinesDraw(pos.x, pos.y, pos.x+vel.x, pos.y+vel.y); + vec2 Pos(x*m_Spacing, y*m_Spacing); + vec2 Vel = m_pCells[y*m_Width+x].m_Vel * 0.01f; + Array[NumItems++] = IGraphics::CLineItem(Pos.x, Pos.y, Pos.x+Vel.x, Pos.y+Vel.y); + if(NumItems == 1024) + { + Graphics()->LinesDraw(Array, 1024); + NumItems = 0; + } } - + + if(NumItems) + Graphics()->LinesDraw(Array, NumItems); Graphics()->LinesEnd(); } -void FLOW::init() +void CFlow::Init() { - if(cells) + if(m_pCells) { - mem_free(cells); - cells = 0; + mem_free(m_pCells); + m_pCells = 0; } - MAPITEM_LAYER_TILEMAP *tilemap = layers_game_layer(); - width = tilemap->width*32/spacing; - height = tilemap->height*32/spacing; + CMapItemLayerTilemap *pTilemap = Layers()->GameLayer(); + m_Width = pTilemap->m_Width*32/m_Spacing; + m_Height = pTilemap->m_Height*32/m_Spacing; // allocate and clear - cells = (CELL *)mem_alloc(sizeof(CELL)*width*height, 1); - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - cells[y*width+x].vel = vec2(0.0f, 0.0f); + m_pCells = (CCell *)mem_alloc(sizeof(CCell)*m_Width*m_Height, 1); + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pCells[y*m_Width+x].m_Vel = vec2(0.0f, 0.0f); } -void FLOW::update() +void CFlow::Update() { - if(!cells) + if(!m_pCells) return; - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - cells[y*width+x].vel *= 0.85f; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pCells[y*m_Width+x].m_Vel *= 0.85f; } -vec2 FLOW::get(vec2 pos) +vec2 CFlow::Get(vec2 Pos) { - if(!cells) + if(!m_pCells) return vec2(0,0); - int x = (int)(pos.x / spacing); - int y = (int)(pos.y / spacing); - if(x < 0 || y < 0 || x >= width || y >= height) + int x = (int)(Pos.x / m_Spacing); + int y = (int)(Pos.y / m_Spacing); + if(x < 0 || y < 0 || x >= m_Width || y >= m_Height) return vec2(0,0); - return cells[y*width+x].vel; + return m_pCells[y*m_Width+x].m_Vel; } -void FLOW::add(vec2 pos, vec2 vel, float size) +void CFlow::Add(vec2 Pos, vec2 Vel, float Size) { - if(!cells) + if(!m_pCells) return; - int x = (int)(pos.x / spacing); - int y = (int)(pos.y / spacing); - if(x < 0 || y < 0 || x >= width || y >= height) + int x = (int)(Pos.x / m_Spacing); + int y = (int)(Pos.y / m_Spacing); + if(x < 0 || y < 0 || x >= m_Width || y >= m_Height) return; - cells[y*width+x].vel += vel; + m_pCells[y*m_Width+x].m_Vel += Vel; } diff --git a/src/game/client/components/flow.h b/src/game/client/components/flow.h new file mode 100644 index 00000000..e8134797 --- /dev/null +++ b/src/game/client/components/flow.h @@ -0,0 +1,28 @@ +#ifndef GAME_CLIENT_COMPONENTS_FLOW_H +#define GAME_CLIENT_COMPONENTS_FLOW_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CFlow : public CComponent +{ + struct CCell + { + vec2 m_Vel; + }; + + CCell *m_pCells; + int m_Height; + int m_Width; + int m_Spacing; + + void DbgRender(); + void Init(); +public: + CFlow(); + + vec2 Get(vec2 Pos); + void Add(vec2 Pos, vec2 Vel, float Size); + void Update(); +}; + +#endif diff --git a/src/game/client/components/flow.hpp b/src/game/client/components/flow.hpp deleted file mode 100644 index 351b1f69..00000000 --- a/src/game/client/components/flow.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class FLOW : public COMPONENT -{ - struct CELL - { - vec2 vel; - }; - - CELL *cells; - int height; - int width; - int spacing; - - void dbg_render(); - void init(); -public: - FLOW(); - - vec2 get(vec2 pos); - void add(vec2 pos, vec2 vel, float size); - void update(); -}; - diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 837322fb..f4a24384 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -1,32 +1,31 @@ -#include <memory.h> // memcmp - -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> - -#include <game/layers.hpp> - -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include <game/client/render.hpp> - -#include "controls.hpp" -#include "camera.hpp" -#include "hud.hpp" -#include "voting.hpp" -#include "binds.hpp" - -HUD::HUD() +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/shared/config.h> + +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> +#include <game/layers.h> +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include <game/client/render.h> + +#include "controls.h" +#include "camera.h" +#include "hud.h" +#include "voting.h" +#include "binds.h" + +CHud::CHud() { - + // won't work if zero + m_AverageFPS = 1.0f; } -void HUD::on_reset() +void CHud::OnReset() { } -void HUD::render_goals() +void CHud::RenderGoals() { // TODO: split this up into these: // render_gametimer @@ -34,41 +33,41 @@ void HUD::render_goals() // render_scorehud // render_warmuptimer - int gameflags = gameclient.snap.gameobj->flags; + int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags; - float whole = 300*Graphics()->ScreenAspect(); - float half = whole/2.0f; + float Whole = 300*Graphics()->ScreenAspect(); + float Half = Whole/2.0f; Graphics()->MapScreen(0,0,300*Graphics()->ScreenAspect(),300); - if(!gameclient.snap.gameobj->sudden_death) + if(!m_pClient->m_Snap.m_pGameobj->m_SuddenDeath) { - char buf[32]; - int time = 0; - if(gameclient.snap.gameobj->time_limit) + char Buf[32]; + int Time = 0; + if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit) { - time = gameclient.snap.gameobj->time_limit*60 - ((client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed()); + Time = m_pClient->m_Snap.m_pGameobj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameobj->m_RoundStartTick)/Client()->GameTickSpeed()); - if(gameclient.snap.gameobj->game_over) - time = 0; + if(m_pClient->m_Snap.m_pGameobj->m_GameOver) + Time = 0; } else - time = (client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed(); + Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameobj->m_RoundStartTick)/Client()->GameTickSpeed(); - str_format(buf, sizeof(buf), "%d:%02d", time /60, time %60); - float w = gfx_text_width(0, 16, buf, -1); - gfx_text(0, half-w/2, 2, 16, buf, -1); + str_format(Buf, sizeof(Buf), "%d:%02d", Time /60, Time %60); + float w = TextRender()->TextWidth(0, 16, Buf, -1); + TextRender()->Text(0, Half-w/2, 2, 16, Buf, -1); } - if(gameclient.snap.gameobj->sudden_death) + if(m_pClient->m_Snap.m_pGameobj->m_SuddenDeath) { - const char *text = "Sudden Death"; - float w = gfx_text_width(0, 16, text, -1); - gfx_text(0, half-w/2, 2, 16, text, -1); + const char *pText = "Sudden Death"; + float w = TextRender()->TextWidth(0, 16, pText, -1); + TextRender()->Text(0, Half-w/2, 2, 16, pText, -1); } // render small score hud - if(!(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) && (gameflags&GAMEFLAG_TEAMS)) + if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) && (GameFlags&GAMEFLAG_TEAMS)) { for(int t = 0; t < 2; t++) { @@ -79,166 +78,171 @@ void HUD::render_goals() Graphics()->SetColor(1,0,0,0.25f); else Graphics()->SetColor(0,0,1,0.25f); - RenderTools()->draw_round_rect(whole-40, 300-40-15+t*20, 50, 18, 5.0f); + RenderTools()->DrawRoundRect(Whole-45, 300-40-15+t*20, 50, 18, 5.0f); Graphics()->QuadsEnd(); - char buf[32]; - str_format(buf, sizeof(buf), "%d", t?gameclient.snap.gameobj->teamscore_blue:gameclient.snap.gameobj->teamscore_red); - float w = gfx_text_width(0, 14, buf, -1); + char Buf[32]; + str_format(Buf, sizeof(Buf), "%d", t?m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue : m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed); + float w = TextRender()->TextWidth(0, 14, Buf, -1); - if(gameflags&GAMEFLAG_FLAGS) + if(GameFlags&GAMEFLAG_FLAGS) { - gfx_text(0, whole-20-w/2+5, 300-40-15+t*20, 14, buf, -1); - if(gameclient.snap.flags[t]) + TextRender()->Text(0, Whole-20-w/2+5, 300-40-15+t*20, 14, Buf, -1); + if(m_pClient->m_Snap.m_paFlags[t]) { - if(gameclient.snap.flags[t]->carried_by == -2 || (gameclient.snap.flags[t]->carried_by == -1 && ((client_tick()/10)&1))) + if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1))) { Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - if(t == 0) RenderTools()->select_sprite(SPRITE_FLAG_RED); - else RenderTools()->select_sprite(SPRITE_FLAG_BLUE); + if(t == 0) RenderTools()->SelectSprite(SPRITE_FLAG_RED); + else RenderTools()->SelectSprite(SPRITE_FLAG_BLUE); - float size = 16; - Graphics()->QuadsDrawTL(whole-40+5, 300-40-15+t*20+1, size/2, size); + float Size = 16; + IGraphics::CQuadItem QuadItem(Whole-40+2, 300-40-15+t*20+1, Size/2, Size); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } - else if(gameclient.snap.flags[t]->carried_by >= 0) + else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0) { - int id = gameclient.snap.flags[t]->carried_by%MAX_CLIENTS; - const char *name = gameclient.clients[id].name; - float w = gfx_text_width(0, 10, name, -1); - gfx_text(0, whole-40-5-w, 300-40-15+t*20+2, 10, name, -1); - TEE_RENDER_INFO info = gameclient.clients[id].render_info; - info.size = 18.0f; + int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS; + const char *pName = m_pClient->m_aClients[Id].m_aName; + float w = TextRender()->TextWidth(0, 10, pName, -1); + TextRender()->Text(0, Whole-40-7-w, 300-40-15+t*20+2, 10, pName, -1); + CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo; + Info.m_Size = 18.0f; - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0), - vec2(whole-40+10, 300-40-15+9+t*20+1)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), + vec2(Whole-40+5, 300-40-15+9+t*20+1)); } } } else - gfx_text(0, whole-20-w/2, 300-40-15+t*20, 14, buf, -1); + TextRender()->Text(0, Whole-20-w/2, 300-40-15+t*20, 14, Buf, -1); } } // render warmup timer - if(gameclient.snap.gameobj->warmup) + if(m_pClient->m_Snap.m_pGameobj->m_Warmup) { - char buf[256]; - float w = gfx_text_width(0, 24, "Warmup", -1); - gfx_text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, 24, "Warmup", -1); + char Buf[256]; + float w = TextRender()->TextWidth(0, 24, "Warmup", -1); + TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, 24, "Warmup", -1); - int seconds = gameclient.snap.gameobj->warmup/SERVER_TICK_SPEED; - if(seconds < 5) - str_format(buf, sizeof(buf), "%d.%d", seconds, (gameclient.snap.gameobj->warmup*10/SERVER_TICK_SPEED)%10); + int Seconds = m_pClient->m_Snap.m_pGameobj->m_Warmup/SERVER_TICK_SPEED; + if(Seconds < 5) + str_format(Buf, sizeof(Buf), "%d.%d", Seconds, (m_pClient->m_Snap.m_pGameobj->m_Warmup*10/SERVER_TICK_SPEED)%10); else - str_format(buf, sizeof(buf), "%d", seconds); - w = gfx_text_width(0, 24, buf, -1); - gfx_text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, 24, buf, -1); + str_format(Buf, sizeof(Buf), "%d", Seconds); + w = TextRender()->TextWidth(0, 24, Buf, -1); + TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, 24, Buf, -1); } } -void HUD::mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group) +void CHud::MapscreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup) { - float points[4]; - RenderTools()->mapscreen_to_world(center_x, center_y, group->parallax_x/100.0f, group->parallax_y/100.0f, - group->offset_x, group->offset_y, Graphics()->ScreenAspect(), 1.0f, points); - Graphics()->MapScreen(points[0], points[1], points[2], points[3]); + float Points[4]; + RenderTools()->MapscreenToWorld(CenterX, CenterY, pGroup->m_ParallaxX/100.0f, pGroup->m_ParallaxY/100.0f, + pGroup->m_OffsetX, pGroup->m_OffsetY, Graphics()->ScreenAspect(), 1.0f, Points); + Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]); } -void HUD::render_fps() +void CHud::RenderFps() { - if(config.cl_showfps) + if(g_Config.m_ClShowfps) { - char buf[512]; - str_format(buf, sizeof(buf), "%d", (int)(1.0f/client_frametime())); - gfx_text(0, width-10-gfx_text_width(0,12,buf,-1), 5, 12, buf, -1); + // calculate avg. fps + float FPS = 1.0f / Client()->FrameTime(); + m_AverageFPS = (m_AverageFPS*(1.0f-(1.0f/m_AverageFPS))) + (FPS*(1.0f/m_AverageFPS)); + char Buf[512]; + str_format(Buf, sizeof(Buf), "%d", (int)m_AverageFPS); + TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,Buf,-1), 5, 12, Buf, -1); } } -void HUD::render_connectionwarning() +void CHud::RenderConnectionWarning() { - if(client_connection_problems()) + if(Client()->ConnectionProblems()) { - const char *text = "Connection Problems..."; - float w = gfx_text_width(0, 24, text, -1); - gfx_text(0, 150*Graphics()->ScreenAspect()-w/2, 50, 24, text, -1); + const char *pText = "Connection Problems..."; + float w = TextRender()->TextWidth(0, 24, pText, -1); + TextRender()->Text(0, 150*Graphics()->ScreenAspect()-w/2, 50, 24, pText, -1); } } -void HUD::render_teambalancewarning() +void CHud::RenderTeambalanceWarning() { // render prompt about team-balance - bool flash = time_get()/(time_freq()/2)%2 == 0; - if (gameclient.snap.gameobj && (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0) + bool Flash = time_get()/(time_freq()/2)%2 == 0; + if (m_pClient->m_Snap.m_pGameobj && (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0) { - if (config.cl_warning_teambalance && abs(gameclient.snap.team_size[0]-gameclient.snap.team_size[1]) >= 2) + int TeamDiff = m_pClient->m_Snap.m_aTeamSize[0]-m_pClient->m_Snap.m_aTeamSize[1]; + if (g_Config.m_ClWarningTeambalance && (TeamDiff >= 2 || TeamDiff <= -2)) { - const char *text = "Please balance teams!"; - if(flash) - gfx_text_color(1,1,0.5f,1); + const char *pText = "Please balance teams!"; + if(Flash) + TextRender()->TextColor(1,1,0.5f,1); else - gfx_text_color(0.7f,0.7f,0.2f,1.0f); - gfx_text(0x0, 5, 50, 6, text, -1); - gfx_text_color(1,1,1,1); + TextRender()->TextColor(0.7f,0.7f,0.2f,1.0f); + TextRender()->Text(0x0, 5, 50, 6, pText, -1); + TextRender()->TextColor(1,1,1,1); } } } -void HUD::render_voting() +void CHud::RenderVoting() { - if(!gameclient.voting->is_voting()) + if(!m_pClient->m_pVoting->IsVoting()) return; Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.40f); - RenderTools()->draw_round_rect(-10, 60-2, 100+10+4+5, 28, 5.0f); + RenderTools()->DrawRoundRect(-10, 60-2, 100+10+4+5, 28, 5.0f); Graphics()->QuadsEnd(); - gfx_text_color(1,1,1,1); + TextRender()->TextColor(1,1,1,1); - char buf[512]; - gfx_text(0x0, 5, 60, 6, gameclient.voting->vote_description(), -1); + char Buf[512]; + TextRender()->Text(0x0, 5, 60, 6, m_pClient->m_pVoting->VoteDescription(), -1); - str_format(buf, sizeof(buf), "%ds left", gameclient.voting->seconds_left()); - float tw = gfx_text_width(0x0, 6, buf, -1); - gfx_text(0x0, 5+100-tw, 60, 6, buf, -1); + str_format(Buf, sizeof(Buf), "%ds left", m_pClient->m_pVoting->SecondsLeft()); + float tw = TextRender()->TextWidth(0x0, 6, Buf, -1); + TextRender()->Text(0x0, 5+100-tw, 60, 6, Buf, -1); - CUIRect base = {5, 70, 100, 4}; - gameclient.voting->render_bars(base, false); + CUIRect Base = {5, 70, 100, 4}; + m_pClient->m_pVoting->RenderBars(Base, false); - const char *yes_key = gameclient.binds->get_key("vote yes"); - const char *no_key = gameclient.binds->get_key("vote no"); - str_format(buf, sizeof(buf), "%s - Vote Yes", yes_key); - base.y += base.h+1; - UI()->DoLabel(&base, buf, 6.0f, -1); - - str_format(buf, sizeof(buf), "Vote No - %s", no_key); - UI()->DoLabel(&base, buf, 6.0f, 1); + const char *pYesKey = m_pClient->m_pBinds->GetKey("vote yes"); + const char *pNoKey = m_pClient->m_pBinds->GetKey("vote no"); + str_format(Buf, sizeof(Buf), "%s - Vote Yes", pYesKey); + Base.y += Base.h+1; + UI()->DoLabel(&Base, Buf, 6.0f, -1); + + str_format(Buf, sizeof(Buf), "Vote No - %s", pNoKey); + UI()->DoLabel(&Base, Buf, 6.0f, 1); } -void HUD::render_cursor() +void CHud::RenderCursor() { - if(!gameclient.snap.local_character) + if(!m_pClient->m_Snap.m_pLocalCharacter) return; - mapscreen_to_group(gameclient.camera->center.x, gameclient.camera->center.y, layers_game_group()); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + MapscreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup()); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); // render cursor - RenderTools()->select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_cursor); - float cursorsize = 64; - RenderTools()->draw_sprite(gameclient.controls->target_pos.x, gameclient.controls->target_pos.y, cursorsize); + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteCursor); + float CursorSize = 64; + RenderTools()->DrawSprite(m_pClient->m_pControls->m_TargetPos.x, m_pClient->m_pControls->m_TargetPos.y, CursorSize); Graphics()->QuadsEnd(); } -void HUD::render_healthandammo() +void CHud::RenderHealthAndAmmo() { //mapscreen_to_group(gacenter_x, center_y, layers_game_group()); @@ -248,61 +252,69 @@ void HUD::render_healthandammo() // render ammo count // render gui stuff - Graphics()->TextureSet(data->images[IMAGE_GAME].id); - Graphics()->MapScreen(0,0,width,300); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); + Graphics()->MapScreen(0,0,m_Width,300); Graphics()->QuadsBegin(); // if weaponstage is active, put a "glow" around the stage ammo - RenderTools()->select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_proj); - for (int i = 0; i < min(gameclient.snap.local_character->ammocount, 10); i++) - Graphics()->QuadsDrawTL(x+i*12,y+24,10,10); - + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj); + IGraphics::CQuadItem Array[10]; + int i; + for (i = 0; i < min(m_pClient->m_Snap.m_pLocalCharacter->m_AmmoCount, 10); i++) + Array[i] = IGraphics::CQuadItem(x+i*12,y+24,10,10); + Graphics()->QuadsDrawTL(Array, i); Graphics()->QuadsEnd(); Graphics()->QuadsBegin(); int h = 0; // render health - RenderTools()->select_sprite(SPRITE_HEALTH_FULL); - for(; h < gameclient.snap.local_character->health; h++) - Graphics()->QuadsDrawTL(x+h*12,y,10,10); + RenderTools()->SelectSprite(SPRITE_HEALTH_FULL); + for(; h < min(m_pClient->m_Snap.m_pLocalCharacter->m_Health, 10); h++) + Array[h] = IGraphics::CQuadItem(x+h*12,y,10,10); + Graphics()->QuadsDrawTL(Array, h); - RenderTools()->select_sprite(SPRITE_HEALTH_EMPTY); + i = 0; + RenderTools()->SelectSprite(SPRITE_HEALTH_EMPTY); for(; h < 10; h++) - Graphics()->QuadsDrawTL(x+h*12,y,10,10); + Array[i++] = IGraphics::CQuadItem(x+h*12,y,10,10); + Graphics()->QuadsDrawTL(Array, i); // render armor meter h = 0; - RenderTools()->select_sprite(SPRITE_ARMOR_FULL); - for(; h < gameclient.snap.local_character->armor; h++) - Graphics()->QuadsDrawTL(x+h*12,y+12,10,10); + RenderTools()->SelectSprite(SPRITE_ARMOR_FULL); + for(; h < min(m_pClient->m_Snap.m_pLocalCharacter->m_Armor, 10); h++) + Array[h] = IGraphics::CQuadItem(x+h*12,y+12,10,10); + Graphics()->QuadsDrawTL(Array, h); - RenderTools()->select_sprite(SPRITE_ARMOR_EMPTY); + i = 0; + RenderTools()->SelectSprite(SPRITE_ARMOR_EMPTY); for(; h < 10; h++) - Graphics()->QuadsDrawTL(x+h*12,y+12,10,10); + Array[i++] = IGraphics::CQuadItem(x+h*12,y+12,10,10); + Graphics()->QuadsDrawTL(Array, i); Graphics()->QuadsEnd(); } -void HUD::on_render() +void CHud::OnRender() { - if(!gameclient.snap.gameobj) + if(!m_pClient->m_Snap.m_pGameobj) return; - width = 300*Graphics()->ScreenAspect(); + m_Width = 300*Graphics()->ScreenAspect(); - bool spectate = false; - if(gameclient.snap.local_info && gameclient.snap.local_info->team == -1) - spectate = true; + bool Spectate = false; + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team == -1) + Spectate = true; - if(gameclient.snap.local_character && !spectate && !(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over)) - render_healthandammo(); - - render_goals(); - render_fps(); - if(client_state() != CLIENTSTATE_DEMOPLAYBACK) - render_connectionwarning(); - render_teambalancewarning(); - render_voting(); - render_cursor(); + if(m_pClient->m_Snap.m_pLocalCharacter && !Spectate && !(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + RenderHealthAndAmmo(); + + RenderGoals(); + RenderFps(); + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + RenderConnectionWarning(); + RenderTeambalanceWarning(); + RenderVoting(); + RenderCursor(); } diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h new file mode 100644 index 00000000..43f0e3a8 --- /dev/null +++ b/src/game/client/components/hud.h @@ -0,0 +1,27 @@ +#ifndef GAME_CLIENT_COMPONENTS_HUD_H +#define GAME_CLIENT_COMPONENTS_HUD_H +#include <game/client/component.h> + +class CHud : public CComponent +{ + float m_Width; + float m_AverageFPS; + + void RenderCursor(); + + void RenderFps(); + void RenderConnectionWarning(); + void RenderTeambalanceWarning(); + void RenderVoting(); + void RenderHealthAndAmmo(); + void RenderGoals(); + + void MapscreenToGroup(float CenterX, float CenterY, struct CMapItemGroup *PGroup); +public: + CHud(); + + virtual void OnReset(); + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/hud.hpp b/src/game/client/components/hud.hpp deleted file mode 100644 index 92ff0122..00000000 --- a/src/game/client/components/hud.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include <game/client/component.hpp> - -class HUD : public COMPONENT -{ - float width; - - void render_cursor(); - - void render_fps(); - void render_connectionwarning(); - void render_teambalancewarning(); - void render_voting(); - void render_healthandammo(); - void render_goals(); - - - void mapscreen_to_group(float center_x, float center_y, struct MAPITEM_GROUP *group); -public: - HUD(); - - virtual void on_reset(); - virtual void on_render(); -}; - diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 3c9e1b79..70479e53 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -1,94 +1,94 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/graphics.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/gamecore.hpp> // get_angle -#include <game/client/gameclient.hpp> -#include <game/client/ui.hpp> -#include <game/client/render.hpp> +#include <game/gamecore.h> // get_angle +#include <game/client/gameclient.h> +#include <game/client/ui.h> +#include <game/client/render.h> -#include <game/client/components/flow.hpp> -#include <game/client/components/effects.hpp> +#include <game/client/components/flow.h> +#include <game/client/components/effects.h> -#include "items.hpp" +#include "items.h" -void ITEMS::render_projectile(const NETOBJ_PROJECTILE *current, int itemid) +void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemId) { // get positions - float curvature = 0; - float speed = 0; - if(current->type == WEAPON_GRENADE) + float Curvature = 0; + float Speed = 0; + if(pCurrent->m_Type == WEAPON_GRENADE) { - curvature = gameclient.tuning.grenade_curvature; - speed = gameclient.tuning.grenade_speed; + Curvature = m_pClient->m_Tuning.m_GrenadeCurvature; + Speed = m_pClient->m_Tuning.m_GrenadeSpeed; } - else if(current->type == WEAPON_SHOTGUN) + else if(pCurrent->m_Type == WEAPON_SHOTGUN) { - curvature = gameclient.tuning.shotgun_curvature; - speed = gameclient.tuning.shotgun_speed; + Curvature = m_pClient->m_Tuning.m_ShotgunCurvature; + Speed = m_pClient->m_Tuning.m_ShotgunSpeed; } - else if(current->type == WEAPON_GUN) + else if(pCurrent->m_Type == WEAPON_GUN) { - curvature = gameclient.tuning.gun_curvature; - speed = gameclient.tuning.gun_speed; + Curvature = m_pClient->m_Tuning.m_GunCurvature; + Speed = m_pClient->m_Tuning.m_GunSpeed; } - float ct = (client_prevtick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime(); - if(ct < 0) + float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + if(Ct < 0) return; // projectile havn't been shot yet - vec2 startpos(current->x, current->y); - vec2 startvel(current->vx/100.0f, current->vy/100.0f); - vec2 pos = calc_pos(startpos, startvel, curvature, speed, ct); - vec2 prevpos = calc_pos(startpos, startvel, curvature, speed, ct-0.001f); + vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); + vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); + vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); + vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - RenderTools()->select_sprite(data->weapons.id[clamp(current->type, 0, NUM_WEAPONS-1)].sprite_proj); - vec2 vel = pos-prevpos; - //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); + vec2 Vel = Pos-PrevPos; + //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); // add particle for this projectile - if(current->type == WEAPON_GRENADE) + if(pCurrent->m_Type == WEAPON_GRENADE) { - gameclient.effects->smoketrail(pos, vel*-1); - gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f); - Graphics()->QuadsSetRotation(client_localtime()*pi*2*2 + itemid); + m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); + m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); + Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemId); } else { - gameclient.effects->bullettrail(pos); - gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f); + m_pClient->m_pEffects->BulletTrail(Pos); + m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); - if(length(vel) > 0.00001f) - Graphics()->QuadsSetRotation(get_angle(vel)); + if(length(Vel) > 0.00001f) + Graphics()->QuadsSetRotation(GetAngle(Vel)); else Graphics()->QuadsSetRotation(0); } - Graphics()->QuadsDraw(pos.x, pos.y, 32, 32); + IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32); + Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); } -void ITEMS::render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *current) +void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent) { - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); - float angle = 0.0f; - float size = 64.0f; - if (current->type == POWERUP_WEAPON) + vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick()); + float Angle = 0.0f; + float Size = 64.0f; + if (pCurrent->m_Type == POWERUP_WEAPON) { - angle = 0; //-pi/6;//-0.25f * pi * 2.0f; - RenderTools()->select_sprite(data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].sprite_body); - size = data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].visual_size; + Angle = 0; //-pi/6;//-0.25f * pi * 2.0f; + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_pSpriteBody); + Size = g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_VisualSize; } else { @@ -98,69 +98,70 @@ void ITEMS::render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *curren SPRITE_PICKUP_WEAPON, SPRITE_PICKUP_NINJA }; - RenderTools()->select_sprite(c[current->type]); + RenderTools()->SelectSprite(c[pCurrent->m_Type]); - if(c[current->type] == SPRITE_PICKUP_NINJA) + if(c[pCurrent->m_Type] == SPRITE_PICKUP_NINJA) { - gameclient.effects->powerupshine(pos, vec2(96,18)); - size *= 2.0f; - pos.x += 10.0f; + m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18)); + Size *= 2.0f; + Pos.x += 10.0f; } } - Graphics()->QuadsSetRotation(angle); + Graphics()->QuadsSetRotation(Angle); - float offset = pos.y/32.0f + pos.x/32.0f; - pos.x += cosf(client_localtime()*2.0f+offset)*2.5f; - pos.y += sinf(client_localtime()*2.0f+offset)*2.5f; - RenderTools()->draw_sprite(pos.x, pos.y, size); + float Offset = Pos.y/32.0f + Pos.x/32.0f; + Pos.x += cosf(Client()->LocalTime()*2.0f+Offset)*2.5f; + Pos.y += sinf(Client()->LocalTime()*2.0f+Offset)*2.5f; + RenderTools()->DrawSprite(Pos.x, Pos.y, Size); Graphics()->QuadsEnd(); } -void ITEMS::render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current) +void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent) { - float angle = 0.0f; - float size = 42.0f; + float Angle = 0.0f; + float Size = 42.0f; Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - if(current->team == 0) // red team - RenderTools()->select_sprite(SPRITE_FLAG_RED); + if(pCurrent->m_Team == 0) // red team + RenderTools()->SelectSprite(SPRITE_FLAG_RED); else - RenderTools()->select_sprite(SPRITE_FLAG_BLUE); + RenderTools()->SelectSprite(SPRITE_FLAG_BLUE); - Graphics()->QuadsSetRotation(angle); + Graphics()->QuadsSetRotation(Angle); - vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); + vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick()); // make sure that the flag isn't interpolated between capture and return - if(prev->carried_by != current->carried_by) - pos = vec2(current->x, current->y); + if(pPrev->m_CarriedBy != pCurrent->m_CarriedBy) + Pos = vec2(pCurrent->m_X, pCurrent->m_Y); // make sure to use predicted position if we are the carrier - if(gameclient.snap.local_info && current->carried_by == gameclient.snap.local_info->cid) - pos = gameclient.local_character_pos; + if(m_pClient->m_Snap.m_pLocalInfo && pCurrent->m_CarriedBy == m_pClient->m_Snap.m_pLocalInfo->m_ClientId) + Pos = m_pClient->m_LocalCharacterPos; - Graphics()->QuadsDraw(pos.x, pos.y-size*0.75f, size, size*2); + IGraphics::CQuadItem QuadItem(Pos.x, Pos.y-Size*0.75f, Size, Size*2); + Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); } -void ITEMS::render_laser(const struct NETOBJ_LASER *current) +void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent) { - vec2 pos = vec2(current->x, current->y); - vec2 from = vec2(current->from_x, current->from_y); - vec2 dir = normalize(pos-from); + vec2 Pos = vec2(pCurrent->m_X, pCurrent->m_Y); + vec2 From = vec2(pCurrent->m_FromX, pCurrent->m_FromY); + vec2 Dir = normalize(Pos-From); - float ticks = client_tick() + client_intratick() - current->start_tick; - float ms = (ticks/50.0f) * 1000.0f; - float a = ms / gameclient.tuning.laser_bounce_delay; + float Ticks = Client()->GameTick() + Client()->IntraGameTick() - pCurrent->m_StartTick; + float Ms = (Ticks/50.0f) * 1000.0f; + float a = Ms / m_pClient->m_Tuning.m_LaserBounceDelay; a = clamp(a, 0.0f, 1.0f); - float ia = 1-a; + float Ia = 1-a; - vec2 out, border; + vec2 Out, Border; Graphics()->BlendNormal(); Graphics()->TextureSet(-1); @@ -170,77 +171,87 @@ void ITEMS::render_laser(const struct NETOBJ_LASER *current) //vec4 outer_color(0.65f,0.85f,1.0f,1.0f); // do outline - vec4 outer_color(0.075f,0.075f,0.25f,1.0f); - Graphics()->SetColor(outer_color.r,outer_color.g,outer_color.b,1.0f); - out = vec2(dir.y, -dir.x) * (7.0f*ia); + vec4 OuterColor(0.075f, 0.075f, 0.25f, 1.0f); + Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); + Out = vec2(Dir.y, -Dir.x) * (7.0f*Ia); - Graphics()->QuadsDrawFreeform( - from.x-out.x, from.y-out.y, - from.x+out.x, from.y+out.y, - pos.x-out.x, pos.y-out.y, - pos.x+out.x, pos.y+out.y - ); + IGraphics::CFreeformItem Freeform( + From.x-Out.x, From.y-Out.y, + From.x+Out.x, From.y+Out.y, + Pos.x-Out.x, Pos.y-Out.y, + Pos.x+Out.x, Pos.y+Out.y); + Graphics()->QuadsDrawFreeform(&Freeform, 1); // do inner - vec4 inner_color(0.5f,0.5f,1.0f,1.0f); - out = vec2(dir.y, -dir.x) * (5.0f*ia); - Graphics()->SetColor(inner_color.r, inner_color.g, inner_color.b, 1.0f); // center + vec4 InnerColor(0.5f, 0.5f, 1.0f, 1.0f); + Out = vec2(Dir.y, -Dir.x) * (5.0f*Ia); + Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center - Graphics()->QuadsDrawFreeform( - from.x-out.x, from.y-out.y, - from.x+out.x, from.y+out.y, - pos.x-out.x, pos.y-out.y, - pos.x+out.x, pos.y+out.y - ); + Freeform = IGraphics::CFreeformItem( + From.x-Out.x, From.y-Out.y, + From.x+Out.x, From.y+Out.y, + Pos.x-Out.x, Pos.y-Out.y, + Pos.x+Out.x, Pos.y+Out.y); + Graphics()->QuadsDrawFreeform(&Freeform, 1); Graphics()->QuadsEnd(); // render head { Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_PARTICLES].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_PARTICLES].m_Id); Graphics()->QuadsBegin(); - int sprites[] = {SPRITE_PART_SPLAT01, SPRITE_PART_SPLAT02, SPRITE_PART_SPLAT03}; - RenderTools()->select_sprite(sprites[client_tick()%3]); - Graphics()->QuadsSetRotation(client_tick()); - Graphics()->SetColor(outer_color.r,outer_color.g,outer_color.b,1.0f); - Graphics()->QuadsDraw(pos.x, pos.y, 24,24); - Graphics()->SetColor(inner_color.r, inner_color.g, inner_color.b, 1.0f); - Graphics()->QuadsDraw(pos.x, pos.y, 20,20); + int Sprites[] = {SPRITE_PART_SPLAT01, SPRITE_PART_SPLAT02, SPRITE_PART_SPLAT03}; + RenderTools()->SelectSprite(Sprites[Client()->GameTick()%3]); + Graphics()->QuadsSetRotation(Client()->GameTick()); + Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); + IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 24, 24); + Graphics()->QuadsDraw(&QuadItem, 1); + Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); + QuadItem = IGraphics::CQuadItem(Pos.x, Pos.y, 20, 20); + Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); } Graphics()->BlendNormal(); } -void ITEMS::on_render() +void CItems::OnRender() { - int num = snap_num_items(SNAP_CURRENT); - for(int i = 0; i < num; i++) + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); + for(int i = 0; i < Num; i++) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - if(item.type == NETOBJTYPE_PROJECTILE) + if(Item.m_Type == NETOBJTYPE_PROJECTILE) { - render_projectile((const NETOBJ_PROJECTILE *)data, item.id); + RenderProjectile((const CNetObj_Projectile *)pData, Item.m_Id); } - else if(item.type == NETOBJTYPE_PICKUP) + else if(Item.m_Type == NETOBJTYPE_PICKUP) { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if(prev) - render_pickup((const NETOBJ_PICKUP *)prev, (const NETOBJ_PICKUP *)data); + const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_Id); + if(pPrev) + RenderPickup((const CNetObj_Pickup *)pPrev, (const CNetObj_Pickup *)pData); } - else if(item.type == NETOBJTYPE_LASER) + else if(Item.m_Type == NETOBJTYPE_LASER) { - render_laser((const NETOBJ_LASER *)data); + RenderLaser((const CNetObj_Laser *)pData); } - else if(item.type == NETOBJTYPE_FLAG) + } + + // render flag + for(int i = 0; i < Num; i++) + { + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); + + if(Item.m_Type == NETOBJTYPE_FLAG) { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if (prev) - render_flag((const NETOBJ_FLAG *)prev, (const NETOBJ_FLAG *)data); + const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_Id); + if (pPrev) + RenderFlag((const CNetObj_Flag *)pPrev, (const CNetObj_Flag *)pData); } } @@ -248,7 +259,7 @@ void ITEMS::on_render() /* for(int i = 0; i < extraproj_num; i++) { - if(extraproj_projectiles[i].start_tick < client_tick()) + if(extraproj_projectiles[i].start_tick < Client()->GameTick()) { extraproj_projectiles[i] = extraproj_projectiles[extraproj_num-1]; extraproj_num--; diff --git a/src/game/client/components/items.h b/src/game/client/components/items.h new file mode 100644 index 00000000..e4525546 --- /dev/null +++ b/src/game/client/components/items.h @@ -0,0 +1,16 @@ +#ifndef GAME_CLIENT_COMPONENTS_ITEMS_H +#define GAME_CLIENT_COMPONENTS_ITEMS_H +#include <game/client/component.h> + +class CItems : public CComponent +{ + void RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemId); + void RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent); + void RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent); + void RenderLaser(const struct CNetObj_Laser *pCurrent); + +public: + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/items.hpp b/src/game/client/components/items.hpp deleted file mode 100644 index 2f33c8c4..00000000 --- a/src/game/client/components/items.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <game/client/component.hpp> - -class ITEMS : public COMPONENT -{ - void render_projectile(const NETOBJ_PROJECTILE *current, int itemid); - void render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *current); - void render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current); - void render_laser(const struct NETOBJ_LASER *current); - -public: - virtual void on_render(); -}; - diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp index e6232b7d..d18dd965 100644 --- a/src/game/client/components/killmessages.cpp +++ b/src/game/client/components/killmessages.cpp @@ -1,127 +1,129 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include "killmessages.hpp" +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include "killmessages.h" -void KILLMESSAGES::on_reset() +void CKillMessages::OnReset() { - killmsg_current = 0; - for(int i = 0; i < killmsg_max; i++) - killmsgs[i].tick = -100000; + m_KillmsgCurrent = 0; + for(int i = 0; i < MAX_KILLMSGS; i++) + m_aKillmsgs[i].m_Tick = -100000; } -void KILLMESSAGES::on_message(int msgtype, void *rawmsg) +void CKillMessages::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_KILLMSG) + if(MsgType == NETMSGTYPE_SV_KILLMSG) { - NETMSG_SV_KILLMSG *msg = (NETMSG_SV_KILLMSG *)rawmsg; + CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg; // unpack messages - KILLMSG kill; - kill.killer = msg->killer; - kill.victim = msg->victim; - kill.weapon = msg->weapon; - kill.mode_special = msg->mode_special; - kill.tick = client_tick(); + CKillMsg Kill; + Kill.m_Killer = pMsg->m_Killer; + Kill.m_Victim = pMsg->m_Victim; + Kill.m_Weapon = pMsg->m_Weapon; + Kill.m_ModeSpecial = pMsg->m_ModeSpecial; + Kill.m_Tick = Client()->GameTick(); // add the message - killmsg_current = (killmsg_current+1)%killmsg_max; - killmsgs[killmsg_current] = kill; + m_KillmsgCurrent = (m_KillmsgCurrent+1)%MAX_KILLMSGS; + m_aKillmsgs[m_KillmsgCurrent] = Kill; } } -void KILLMESSAGES::on_render() +void CKillMessages::OnRender() { - float width = 400*3.0f*Graphics()->ScreenAspect(); - float height = 400*3.0f; + float Width = 400*3.0f*Graphics()->ScreenAspect(); + float Height = 400*3.0f; - Graphics()->MapScreen(0, 0, width*1.5f, height*1.5f); - float startx = width*1.5f-10.0f; + Graphics()->MapScreen(0, 0, Width*1.5f, Height*1.5f); + float StartX = Width*1.5f-10.0f; float y = 20.0f; - for(int i = 0; i < killmsg_max; i++) + for(int i = 0; i < MAX_KILLMSGS; i++) { - int r = (killmsg_current+i+1)%killmsg_max; - if(client_tick() > killmsgs[r].tick+50*10) + int r = (m_KillmsgCurrent+i+1)%MAX_KILLMSGS; + if(Client()->GameTick() > m_aKillmsgs[r].m_Tick+50*10) continue; - float font_size = 36.0f; - float killername_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].killer].name, -1); - float victimname_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].victim].name, -1); + float FontSize = 36.0f; + float KillerNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1); + float VictimNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1); - float x = startx; + float x = StartX; // render victim name - x -= victimname_w; - gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].victim].name, -1); + x -= VictimNameW; + TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1); // render victim tee x -= 24.0f; - if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS) + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_FLAGS) { - if(killmsgs[r].mode_special&1) + if(m_aKillmsgs[r].m_ModeSpecial&1) { Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - if(gameclient.clients[killmsgs[r].victim].team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE); - else RenderTools()->select_sprite(SPRITE_FLAG_RED); + if(m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE); + else RenderTools()->SelectSprite(SPRITE_FLAG_RED); - float size = 56.0f; - Graphics()->QuadsDrawTL(x, y-16, size/2, size); + float Size = 56.0f; + IGraphics::CQuadItem QuadItem(x, y-16, Size/2, Size); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } } - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &gameclient.clients[killmsgs[r].victim].render_info, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_RenderInfo, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28)); x -= 32.0f; // render weapon x -= 44.0f; - if (killmsgs[r].weapon >= 0) + if (m_aKillmsgs[r].m_Weapon >= 0) { - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - RenderTools()->select_sprite(data->weapons.id[killmsgs[r].weapon].sprite_body); - RenderTools()->draw_sprite(x, y+28, 96); + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_aKillmsgs[r].m_Weapon].m_pSpriteBody); + RenderTools()->DrawSprite(x, y+28, 96); Graphics()->QuadsEnd(); } x -= 52.0f; - if(killmsgs[r].victim != killmsgs[r].killer) + if(m_aKillmsgs[r].m_Victim != m_aKillmsgs[r].m_Killer) { - if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS) + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_FLAGS) { - if(killmsgs[r].mode_special&2) + if(m_aKillmsgs[r].m_ModeSpecial&2) { Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - if(gameclient.clients[killmsgs[r].killer].team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); - else RenderTools()->select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); + if(m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); + else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); - float size = 56.0f; - Graphics()->QuadsDrawTL(x-56, y-16, size/2, size); + float Size = 56.0f; + IGraphics::CQuadItem QuadItem(x-56, y-16, Size/2, Size); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } } // render killer tee x -= 24.0f; - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &gameclient.clients[killmsgs[r].killer].render_info, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_RenderInfo, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28)); x -= 32.0f; // render killer name - x -= killername_w; - gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].killer].name, -1); + x -= KillerNameW; + TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1); } y += 44; diff --git a/src/game/client/components/killmessages.h b/src/game/client/components/killmessages.h new file mode 100644 index 00000000..720b10ae --- /dev/null +++ b/src/game/client/components/killmessages.h @@ -0,0 +1,31 @@ +#ifndef GAME_CLIENT_COMPONENTS_KILLMESSAGES_H +#define GAME_CLIENT_COMPONENTS_KILLMESSAGES_H +#include <game/client/component.h> + +class CKillMessages : public CComponent +{ +public: + // kill messages + struct CKillMsg + { + int m_Weapon; + int m_Victim; + int m_Killer; + int m_ModeSpecial; // for CTF, if the guy is carrying a flag for example + int m_Tick; + }; + + enum + { + MAX_KILLMSGS = 5, + }; + + CKillMsg m_aKillmsgs[MAX_KILLMSGS]; + int m_KillmsgCurrent; + + virtual void OnReset(); + virtual void OnRender(); + virtual void OnMessage(int MsgType, void *pRawMsg); +}; + +#endif diff --git a/src/game/client/components/killmessages.hpp b/src/game/client/components/killmessages.hpp deleted file mode 100644 index f29e0bdf..00000000 --- a/src/game/client/components/killmessages.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include <game/client/component.hpp> - -class KILLMESSAGES : public COMPONENT -{ -public: - // kill messages - struct KILLMSG - { - int weapon; - int victim; - int killer; - int mode_special; // for CTF, if the guy is carrying a flag for example - int tick; - }; - - static const int killmsg_max = 5; - KILLMSG killmsgs[killmsg_max]; - int killmsg_current; - - virtual void on_reset(); - virtual void on_render(); - virtual void on_message(int msgtype, void *rawmsg); -}; - diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index 51194853..9be450d1 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -1,45 +1,48 @@ -#include <engine/client/graphics.h> -#include <game/client/component.hpp> -#include <game/mapitems.hpp> +#include <engine/graphics.h> +#include <engine/map.h> +#include <game/client/component.h> +#include <game/mapitems.h> -#include "mapimages.hpp" +#include "mapimages.h" -MAPIMAGES::MAPIMAGES() +CMapImages::CMapImages() { - count = 0; + m_Count = 0; } -void MAPIMAGES::on_mapload() +void CMapImages::OnMapLoad() { + IMap *pMap = Kernel()->RequestInterface<IMap>(); + // unload all textures - for(int i = 0; i < count; i++) + for(int i = 0; i < m_Count; i++) { - Graphics()->UnloadTexture(textures[i]); - textures[i] = -1; + Graphics()->UnloadTexture(m_aTextures[i]); + m_aTextures[i] = -1; } - count = 0; + m_Count = 0; - int start; - map_get_type(MAPITEMTYPE_IMAGE, &start, &count); + int Start; + pMap->GetType(MAPITEMTYPE_IMAGE, &Start, &m_Count); // load new textures - for(int i = 0; i < count; i++) + for(int i = 0; i < m_Count; i++) { - textures[i] = 0; + m_aTextures[i] = 0; - MAPITEM_IMAGE *img = (MAPITEM_IMAGE *)map_get_item(start+i, 0, 0); - if(img->external) + CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start+i, 0, 0); + if(pImg->m_External) { - char buf[256]; - char *name = (char *)map_get_data(img->image_name); - str_format(buf, sizeof(buf), "mapres/%s.png", name); - textures[i] = Graphics()->LoadTexture(buf, IMG_AUTO, 0); + char Buf[256]; + char *pName = (char *)pMap->GetData(pImg->m_ImageName); + str_format(Buf, sizeof(Buf), "mapres/%s.png", pName); + m_aTextures[i] = Graphics()->LoadTexture(Buf, CImageInfo::FORMAT_AUTO, 0); } else { - void *data = map_get_data(img->image_data); - textures[i] = Graphics()->LoadTextureRaw(img->width, img->height, IMG_RGBA, data, IMG_RGBA, 0); - map_unload_data(img->image_data); + void *pData = pMap->GetData(pImg->m_ImageData); + m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, CImageInfo::FORMAT_RGBA, pData, CImageInfo::FORMAT_RGBA, 0); + pMap->UnloadData(pImg->m_ImageData); } } } diff --git a/src/game/client/components/mapimages.h b/src/game/client/components/mapimages.h new file mode 100644 index 00000000..2ef5fc32 --- /dev/null +++ b/src/game/client/components/mapimages.h @@ -0,0 +1,18 @@ +#ifndef GAME_CLIENT_COMPONENTS_MAPIMAGES_H +#define GAME_CLIENT_COMPONENTS_MAPIMAGES_H +#include <game/client/component.h> + +class CMapImages : public CComponent +{ + int m_aTextures[64]; + int m_Count; +public: + CMapImages(); + + int Get(int Index) const { return m_aTextures[Index]; } + int Num() const { return m_Count; } + + virtual void OnMapLoad(); +}; + +#endif diff --git a/src/game/client/components/mapimages.hpp b/src/game/client/components/mapimages.hpp deleted file mode 100644 index cba46033..00000000 --- a/src/game/client/components/mapimages.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#include <game/client/component.hpp> - -class MAPIMAGES : public COMPONENT -{ - int textures[64]; - int count; -public: - MAPIMAGES(); - - int get(int index) const { return textures[index]; } - int num() const { return count; } - - virtual void on_mapload(); -}; - diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 75f91521..202ea2da 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -1,167 +1,192 @@ -#include <engine/client/graphics.h> +#include <stdio.h> +#include <engine/graphics.h> +#include <engine/keys.h> //temp +#include <engine/shared/config.h> -#include <game/layers.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/component.hpp> -#include <game/client/render.hpp> +#include <game/layers.h> +#include <game/client/gameclient.h> +#include <game/client/component.h> +#include <game/client/render.h> -#include <game/client/components/camera.hpp> -#include <game/client/components/mapimages.hpp> +#include <game/client/components/camera.h> +#include <game/client/components/mapimages.h> -#include "maplayers.hpp" +#include "maplayers.h" -MAPLAYERS::MAPLAYERS(int t) +CMapLayers::CMapLayers(int t) { - type = t; + m_Type = t; + m_pLayers = 0; } +void CMapLayers::OnInit() +{ + m_pLayers = Layers(); +} -void MAPLAYERS::mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group) + +void CMapLayers::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup) { - float points[4]; - RenderTools()->mapscreen_to_world(center_x, center_y, group->parallax_x/100.0f, group->parallax_y/100.0f, - group->offset_x, group->offset_y, Graphics()->ScreenAspect(), 1.0f, points); - Graphics()->MapScreen(points[0], points[1], points[2], points[3]); + float Points[4]; + RenderTools()->MapscreenToWorld(CenterX, CenterY, pGroup->m_ParallaxX/100.0f, pGroup->m_ParallaxY/100.0f, + pGroup->m_OffsetX, pGroup->m_OffsetY, Graphics()->ScreenAspect(), 1.0f, Points); + Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]); } -void MAPLAYERS::envelope_eval(float time_offset, int env, float *channels, void *user) +void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) { - MAPLAYERS *pThis = (MAPLAYERS *)user; - channels[0] = 0; - channels[1] = 0; - channels[2] = 0; - channels[3] = 0; + CMapLayers *pThis = (CMapLayers *)pUser; + pChannels[0] = 0; + pChannels[1] = 0; + pChannels[2] = 0; + pChannels[3] = 0; - ENVPOINT *points; + CEnvPoint *pPoints; { - int start, num; - map_get_type(MAPITEMTYPE_ENVPOINTS, &start, &num); - if(num) - points = (ENVPOINT *)map_get_item(start, 0, 0); + int Start, Num; + pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num); + if(Num) + pPoints = (CEnvPoint *)pThis->m_pLayers->Map()->GetItem(Start, 0, 0); } - int start, num; - map_get_type(MAPITEMTYPE_ENVELOPE, &start, &num); + int Start, Num; + pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num); - if(env >= num) + if(Env >= Num) return; - MAPITEM_ENVELOPE *item = (MAPITEM_ENVELOPE *)map_get_item(start+env, 0, 0); - pThis->RenderTools()->render_eval_envelope(points+item->start_point, item->num_points, 4, client_localtime()+time_offset, channels); + CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0); + pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, pThis->Client()->LocalTime()+TimeOffset, pChannels); } -void MAPLAYERS::on_render() +void CMapLayers::OnRender() { - if(client_state() != CLIENTSTATE_ONLINE && client_state() != CLIENTSTATE_DEMOPLAYBACK) + if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK) return; - CUIRect screen; - Graphics()->GetScreen(&screen.x, &screen.y, &screen.w, &screen.h); + CUIRect Screen; + Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h); - vec2 center = gameclient.camera->center; + vec2 Center = m_pClient->m_pCamera->m_Center; //float center_x = gameclient.camera->center.x; //float center_y = gameclient.camera->center.y; - bool passed_gamelayer = false; + bool PassedGameLayer = false; - for(int g = 0; g < layers_num_groups(); g++) + for(int g = 0; g < m_pLayers->NumGroups(); g++) { - MAPITEM_GROUP *group = layers_get_group(g); + CMapItemGroup *pGroup = m_pLayers->GetGroup(g); - if(!config.gfx_noclip && group->version >= 2 && group->use_clipping) + if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) { // set clipping - float points[4]; - mapscreen_to_group(center.x, center.y, layers_game_group()); - Graphics()->GetScreen(&points[0], &points[1], &points[2], &points[3]); - float x0 = (group->clip_x - points[0]) / (points[2]-points[0]); - float y0 = (group->clip_y - points[1]) / (points[3]-points[1]); - float x1 = ((group->clip_x+group->clip_w) - points[0]) / (points[2]-points[0]); - float y1 = ((group->clip_y+group->clip_h) - points[1]) / (points[3]-points[1]); + float Points[4]; + MapScreenToGroup(Center.x, Center.y, m_pLayers->GameGroup()); + Graphics()->GetScreen(&Points[0], &Points[1], &Points[2], &Points[3]); + float x0 = (pGroup->m_ClipX - Points[0]) / (Points[2]-Points[0]); + float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]); + float x1 = ((pGroup->m_ClipX+pGroup->m_ClipW) - Points[0]) / (Points[2]-Points[0]); + float y1 = ((pGroup->m_ClipY+pGroup->m_ClipH) - Points[1]) / (Points[3]-Points[1]); Graphics()->ClipEnable((int)(x0*Graphics()->ScreenWidth()), (int)(y0*Graphics()->ScreenHeight()), (int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight())); } - mapscreen_to_group(center.x, center.y, group); + MapScreenToGroup(Center.x, Center.y, pGroup); - for(int l = 0; l < group->num_layers; l++) + for(int l = 0; l < pGroup->m_NumLayers; l++) { - MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l); - bool render = false; - bool is_game_layer = false; + CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l); + bool Render = false; + bool IsGameLayer = false; - if(layer == (MAPITEM_LAYER*)layers_game_layer()) + if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer()) { - is_game_layer = true; - passed_gamelayer = 1; + IsGameLayer = true; + PassedGameLayer = 1; } // skip rendering if detail layers if not wanted - if(layer->flags&LAYERFLAG_DETAIL && !config.gfx_high_detail && !is_game_layer) + if(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer) continue; - if(type == -1) - render = true; - else if(type == 0) + if(m_Type == -1) + Render = true; + else if(m_Type == 0) { - if(passed_gamelayer) + if(PassedGameLayer) return; - render = true; + Render = true; } else { - if(passed_gamelayer && !is_game_layer) - render = true; + if(PassedGameLayer && !IsGameLayer) + Render = true; } - if(render && !is_game_layer) + if(pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyPressed(KEY_KP0)) + { + CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; + CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data); + char buf[256]; + str_format(buf, sizeof(buf), "%d%d_%dx%d", g, l, pTMap->m_Width, pTMap->m_Height); + FILE *f = fopen(buf, "w"); + for(int y = 0; y < pTMap->m_Height; y++) + { + for(int x = 0; x < pTMap->m_Width; x++) + fprintf(f, "%d,", pTiles[y*pTMap->m_Width + x].m_Index); + fprintf(f, "\n"); + } + fclose(f); + } + + if(Render && !IsGameLayer) { //layershot_begin(); - if(layer->type == LAYERTYPE_TILES) + if(pLayer->m_Type == LAYERTYPE_TILES) { - MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer; - if(tmap->image == -1) + CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; + if(pTMap->m_Image == -1) Graphics()->TextureSet(-1); else - Graphics()->TextureSet(gameclient.mapimages->get(tmap->image)); + Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pTMap->m_Image)); - TILE *tiles = (TILE *)map_get_data(tmap->data); + CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data); Graphics()->BlendNone(); - RenderTools()->render_tilemap(tiles, tmap->width, tmap->height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE); + RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE); Graphics()->BlendNormal(); - RenderTools()->render_tilemap(tiles, tmap->width, tmap->height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT); + RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, vec4(1,1,1,1), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT); } - else if(layer->type == LAYERTYPE_QUADS) + else if(pLayer->m_Type == LAYERTYPE_QUADS) { - MAPITEM_LAYER_QUADS *qlayer = (MAPITEM_LAYER_QUADS *)layer; - if(qlayer->image == -1) + CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer; + if(pQLayer->m_Image == -1) Graphics()->TextureSet(-1); else - Graphics()->TextureSet(gameclient.mapimages->get(qlayer->image)); + Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pQLayer->m_Image)); - QUAD *quads = (QUAD *)map_get_data_swapped(qlayer->data); + CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data); Graphics()->BlendNone(); - RenderTools()->render_quads(quads, qlayer->num_quads, LAYERRENDERFLAG_OPAQUE, envelope_eval, this); + RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_OPAQUE, EnvelopeEval, this); Graphics()->BlendNormal(); - RenderTools()->render_quads(quads, qlayer->num_quads, LAYERRENDERFLAG_TRANSPARENT, envelope_eval, this); + RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, this); } //layershot_end(); } } - if(!config.gfx_noclip) + if(!g_Config.m_GfxNoclip) Graphics()->ClipDisable(); } - if(!config.gfx_noclip) + if(!g_Config.m_GfxNoclip) Graphics()->ClipDisable(); // reset the screen like it was before - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); } diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h new file mode 100644 index 00000000..9f70d9cb --- /dev/null +++ b/src/game/client/components/maplayers.h @@ -0,0 +1,24 @@ +#ifndef GAME_CLIENT_COMPONENTS_MAPLAYERS_H +#define GAME_CLIENT_COMPONENTS_MAPLAYERS_H +#include <game/client/component.h> + +class CMapLayers : public CComponent +{ + CLayers *m_pLayers; // todo refactor: maybe remove it and access it through client* + int m_Type; + + void MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup); + static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); +public: + enum + { + TYPE_BACKGROUND=0, + TYPE_FOREGROUND, + }; + + CMapLayers(int Type); + virtual void OnInit(); + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/maplayers.hpp b/src/game/client/components/maplayers.hpp deleted file mode 100644 index c8b154b2..00000000 --- a/src/game/client/components/maplayers.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <game/client/component.hpp> - -class MAPLAYERS : public COMPONENT -{ - int type; - - void mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group); - static void envelope_eval(float time_offset, int env, float *channels, void *user); -public: - enum - { - TYPE_BACKGROUND=0, - TYPE_FOREGROUND, - }; - - MAPLAYERS(int type); - virtual void on_render(); -}; - diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 5f1bbf42..76ee2e5e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1,45 +1,45 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <stdio.h> +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <math.h> -#include <string.h> -#include <stdlib.h> #include <base/system.h> -#include <base/math.hpp> -#include <base/vmath.hpp> +#include <base/math.h> +#include <base/vmath.h> -#include "menus.hpp" -#include "skins.hpp" +#include "menus.h" +#include "skins.h" -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/serverbrowser.h> +#include <engine/keys.h> +#include <engine/shared/config.h> -#include <game/version.hpp> -#include <game/generated/g_protocol.hpp> +#include <game/version.h> +#include <game/generated/protocol.h> -#include <game/generated/gc_data.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/lineinput.hpp> -#include <game/localization.hpp> +#include <game/generated/client_data.h> +#include <game/client/gameclient.h> +#include <game/client/lineinput.h> +#include <game/localization.h> #include <mastersrv/mastersrv.h> -vec4 MENUS::gui_color; -vec4 MENUS::color_tabbar_inactive_outgame; -vec4 MENUS::color_tabbar_active_outgame; -vec4 MENUS::color_tabbar_inactive; -vec4 MENUS::color_tabbar_active; -vec4 MENUS::color_tabbar_inactive_ingame; -vec4 MENUS::color_tabbar_active_ingame; +vec4 CMenus::ms_GuiColor; +vec4 CMenus::ms_ColorTabbarInactiveOutgame; +vec4 CMenus::ms_ColorTabbarActiveOutgame; +vec4 CMenus::ms_ColorTabbarInactive; +vec4 CMenus::ms_ColorTabbarActive; +vec4 CMenus::ms_ColorTabbarInactiveIngame; +vec4 CMenus::ms_ColorTabbarActiveIngame; -float MENUS::button_height = 25.0f; -float MENUS::listheader_height = 17.0f; -float MENUS::fontmod_height = 0.8f; +float CMenus::ms_ButtonHeight = 25.0f; +float CMenus::ms_ListheaderHeight = 17.0f; +float CMenus::ms_FontmodHeight = 0.8f; -INPUT_EVENT MENUS::inputevents[MAX_INPUTEVENTS]; -int MENUS::num_inputevents; +IInput::CEvent CMenus::m_aInputEvents[MAX_INPUTEVENTS]; +int CMenus::m_NumInputEvents; -inline float hue_to_rgb(float v1, float v2, float h) +inline float HueToRgb(float v1, float v2, float h) { if(h < 0) h += 1; if(h > 1) h -= 1; @@ -49,53 +49,54 @@ inline float hue_to_rgb(float v1, float v2, float h) return v1; } -inline vec3 hsl_to_rgb(vec3 in) +inline vec3 HslToRgb(vec3 In) { float v1, v2; - vec3 out; + vec3 Out; - if(in.s == 0) + if(In.s == 0) { - out.r = in.l; - out.g = in.l; - out.b = in.l; + Out.r = In.l; + Out.g = In.l; + Out.b = In.l; } else { - if(in.l < 0.5f) - v2 = in.l * (1 + in.s); + if(In.l < 0.5f) + v2 = In.l * (1 + In.s); else - v2 = (in.l+in.s) - (in.s*in.l); + v2 = (In.l+In.s) - (In.s*In.l); - v1 = 2 * in.l - v2; + v1 = 2 * In.l - v2; - out.r = hue_to_rgb(v1, v2, in.h + (1.0f/3.0f)); - out.g = hue_to_rgb(v1, v2, in.h); - out.b = hue_to_rgb(v1, v2, in.h - (1.0f/3.0f)); + Out.r = HueToRgb(v1, v2, In.h + (1.0f/3.0f)); + Out.g = HueToRgb(v1, v2, In.h); + Out.b = HueToRgb(v1, v2, In.h - (1.0f/3.0f)); } - return out; + return Out; } -MENUS::MENUS() +CMenus::CMenus() { - popup = POPUP_NONE; - active_page = PAGE_INTERNET; - game_page = PAGE_GAME; + m_Popup = POPUP_NONE; + m_ActivePage = PAGE_INTERNET; + m_GamePage = PAGE_GAME; - need_restart = false; - need_sendinfo = false; - menu_active = true; + m_NeedRestart = false; + m_NeedSendinfo = false; + m_MenuActive = true; + m_UseMouseButtons = true; - escape_pressed = false; - enter_pressed = false; - num_inputevents = 0; + m_EscapePressed = false; + m_EnterPressed = false; + m_NumInputEvents = 0; - last_input = time_get(); + m_LastInput = time_get(); } -vec4 MENUS::button_color_mul(const void *pID) +vec4 CMenus::ButtonColorMul(const void *pID) { if(UI()->ActiveItem() == pID) return vec4(1,1,1,0.5f); @@ -104,69 +105,69 @@ vec4 MENUS::button_color_mul(const void *pID) return vec4(1,1,1,1); } -int MENUS::DoButton_BrowseIcon(int What, const CUIRect *pRect) +int CMenus::DoButton_BrowseIcon(int What, const CUIRect *pRect) { - Graphics()->TextureSet(data->images[IMAGE_BROWSEICONS].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_BROWSEICONS].m_Id); Graphics()->QuadsBegin(); - RenderTools()->select_sprite(What); - Graphics()->QuadsDrawTL(pRect->x, pRect->y, pRect->w, pRect->h); + RenderTools()->SelectSprite(What); + IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); return 0; } -int MENUS::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f); - UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0); + RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f); + UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int MENUS::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f); - UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0); - return UI()->DoButtonLogic(pID, pText, Checked, pRect); + RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f); + UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0); } -int MENUS::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) +int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) { vec4 ColorMod(1,1,1,1); if(Checked) - RenderTools()->DrawUIRect(pRect, color_tabbar_active, Corners, 10.0f); + RenderTools()->DrawUIRect(pRect, ms_ColorTabbarActive, Corners, 10.0f); else - RenderTools()->DrawUIRect(pRect, color_tabbar_inactive, Corners, 10.0f); - UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0); + RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, Corners, 10.0f); + UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int MENUS::DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { if(Checked) - RenderTools()->DrawUIRect(pRect, color_tabbar_active, CUI::CORNER_R, 10.0f); + RenderTools()->DrawUIRect(pRect, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f); else - RenderTools()->DrawUIRect(pRect, color_tabbar_inactive, CUI::CORNER_R, 10.0f); - UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, 0); + RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, CUI::CORNER_R, 10.0f); + UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int MENUS::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect) -//void MENUS::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) +int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +//void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) { if(Checked) RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f), CUI::CORNER_T, 5.0f); CUIRect t; pRect->VSplitLeft(5.0f, 0, &t); - UI()->DoLabel(&t, pText, pRect->h*fontmod_height, -1); + UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight, -1); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int MENUS::DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { if(Checked) { @@ -174,12 +175,12 @@ int MENUS::DoButton_ListRow(const void *pID, const char *pText, int Checked, con sr.Margin(1.5f, &sr); RenderTools()->DrawUIRect(&sr, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); } - UI()->DoLabel(pRect, pText, pRect->h*fontmod_height, -1); + UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, -1); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int MENUS::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect) -//void MENUS::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra) +int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect) +//void CMenus::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra) { CUIRect c = *pRect; CUIRect t = *pRect; @@ -189,57 +190,59 @@ int MENUS::DoButton_CheckBox_Common(const void *pID, const char *pText, const ch t.VSplitLeft(5.0f, 0, &t); c.Margin(2.0f, &c); - RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 3.0f); + RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 3.0f); c.y += 2; - UI()->DoLabel(&c, pBoxText, pRect->h*fontmod_height*0.6f, 0); - UI()->DoLabel(&t, pText, pRect->h*fontmod_height*0.8f, -1); + UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, 0); + UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, -1); return UI()->DoButtonLogic(pID, pText, 0, pRect); } -int MENUS::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { return DoButton_CheckBox_Common(pID, pText, Checked?"X":"", pRect); } -int MENUS::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - char buf[16]; - str_format(buf, sizeof(buf), "%d", Checked); - return DoButton_CheckBox_Common(pID, pText, buf, pRect); + char aBuf[16]; + str_format(aBuf, sizeof(aBuf), "%d", Checked); + return DoButton_CheckBox_Common(pID, pText, aBuf, pRect); } -int MENUS::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden) +int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden, int Corners) { int Inside = UI()->MouseInside(pRect); - int ReturnValue = 0; - static int AtIndex = 0; + bool ReturnValue = false; + static int s_AtIndex = 0; if(UI()->LastActiveItem() == pID) { - int Len = strlen(pStr); + int Len = str_length(pStr); + if(Len == 0) + s_AtIndex = 0; if(Inside && UI()->MouseButton(0)) { - int mx_rel = (int)(UI()->MouseX() - pRect->x); + int MxRel = (int)(UI()->MouseX() - pRect->x); - for (int i = 1; i <= Len; i++) + for(int i = 1; i <= Len; i++) { - if (gfx_text_width(0, FontSize, pStr, i) + 10 > mx_rel) + if(TextRender()->TextWidth(0, FontSize, pStr, i) + 10 > MxRel) { - AtIndex = i - 1; + s_AtIndex = i - 1; break; } - if (i == Len) - AtIndex = Len; + if(i == Len) + s_AtIndex = Len; } } - for(int i = 0; i < num_inputevents; i++) + for(int i = 0; i < m_NumInputEvents; i++) { - Len = strlen(pStr); - LINEINPUT::manipulate(inputevents[i], pStr, StrSize, &Len, &AtIndex); + Len = str_length(pStr); + ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, &Len, &s_AtIndex); } } @@ -264,35 +267,41 @@ int MENUS::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi UI()->SetHotItem(pID); CUIRect Textbox = *pRect; - RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); - Textbox.VMargin(5.0f, &Textbox); + RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f); + Textbox.VMargin(3.0f, &Textbox); const char *pDisplayStr = pStr; char aStars[128]; if(Hidden) { - unsigned s = strlen(pStr); + unsigned s = str_length(pStr); if(s >= sizeof(aStars)) s = sizeof(aStars)-1; - memset(aStars, '*', s); + for(unsigned int i = 0; i < s; ++i) + aStars[i] = '*'; aStars[s] = 0; pDisplayStr = aStars; } UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1); - if (UI()->LastActiveItem() == pID && !JustGotActive) + //TODO: make it blink + if(UI()->LastActiveItem() == pID && !JustGotActive) { - float w = gfx_text_width(0, FontSize, pDisplayStr, AtIndex); + float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); + Textbox = *pRect; + Textbox.VSplitLeft(2.0f, 0, &Textbox); Textbox.x += w*UI()->Scale(); - UI()->DoLabel(&Textbox, "_", FontSize, -1); + Textbox.y -= FontSize/10.f; + + UI()->DoLabel(&Textbox, "|", FontSize*1.1f, -1); } return ReturnValue; } -float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) +float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) { CUIRect Handle; static float OffsetY; @@ -300,7 +309,7 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) Handle.y += (pRect->h-Handle.h)*Current; - /* logic */ + // logic float ReturnValue = Current; int Inside = UI()->MouseInside(&Handle); @@ -309,10 +318,10 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - float min = pRect->y; - float max = pRect->h-Handle.h; - float cur = UI()->MouseY()-OffsetY; - ReturnValue = (cur-min)/max; + float Min = pRect->y; + float Max = pRect->h-Handle.h; + float Cur = UI()->MouseY()-OffsetY; + ReturnValue = (Cur-Min)/Max; if(ReturnValue < 0.0f) ReturnValue = 0.0f; if(ReturnValue > 1.0f) ReturnValue = 1.0f; } @@ -341,14 +350,14 @@ float MENUS::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) Slider = Handle; Slider.Margin(5.0f, &Slider); - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 2.5f); + RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); return ReturnValue; } -float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) +float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) { CUIRect Handle; static float OffsetX; @@ -356,7 +365,7 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) Handle.x += (pRect->w-Handle.w)*Current; - /* logic */ + // logic float ReturnValue = Current; int Inside = UI()->MouseInside(&Handle); @@ -365,10 +374,10 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - float min = pRect->x; - float max = pRect->w-Handle.w; - float cur = UI()->MouseX()-OffsetX; - ReturnValue = (cur-min)/max; + float Min = pRect->x; + float Max = pRect->w-Handle.w; + float Cur = UI()->MouseX()-OffsetX; + ReturnValue = (Cur-Min)/Max; if(ReturnValue < 0.0f) ReturnValue = 0.0f; if(ReturnValue > 1.0f) ReturnValue = 1.0f; } @@ -397,12 +406,12 @@ float MENUS::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) Slider = Handle; Slider.Margin(5.0f, &Slider); - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*button_color_mul(pID), CUI::CORNER_ALL, 2.5f); + RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); return ReturnValue; } -int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key) +int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) { // process static void *pGrabbedID = 0; @@ -415,10 +424,10 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key) if(UI()->ActiveItem() == pID) { - if(binder.got_key) + if(m_Binder.m_GotKey) { - NewKey = binder.key.key; - binder.got_key = false; + NewKey = m_Binder.m_Key.m_Key; + m_Binder.m_GotKey = false; UI()->SetActiveItem(0); MouseReleased = false; pGrabbedID = pID; @@ -428,8 +437,8 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key) { if(UI()->MouseButton(0) && MouseReleased) { - binder.take_key = true; - binder.got_key = false; + m_Binder.m_TakeKey = true; + m_Binder.m_GotKey = false; UI()->SetActiveItem(pID); } } @@ -445,185 +454,185 @@ int MENUS::DoKeyReader(void *pID, const CUIRect *pRect, int Key) if(Key == 0) DoButton_KeySelect(pID, "", 0, pRect); else - DoButton_KeySelect(pID, inp_key_name(Key), 0, pRect); + DoButton_KeySelect(pID, Input()->KeyName(Key), 0, pRect); } return NewKey; } -int MENUS::render_menubar(CUIRect r) +int CMenus::RenderMenubar(CUIRect r) { - CUIRect box = r; - CUIRect button; + CUIRect Box = r; + CUIRect Button; - int active_page = config.ui_page; - int new_page = -1; + m_ActivePage = g_Config.m_UiPage; + int NewPage = -1; - if(client_state() != CLIENTSTATE_OFFLINE) - active_page = game_page; + if(Client()->State() != IClient::STATE_OFFLINE) + m_ActivePage = m_GamePage; - if(client_state() == CLIENTSTATE_OFFLINE) + if(Client()->State() == IClient::STATE_OFFLINE) { - /* offline menus */ + // offline menus if(0) // this is not done yet { - box.VSplitLeft(90.0f, &button, &box); - static int news_button=0; - if (DoButton_MenuTab(&news_button, localize("News"), active_page==PAGE_NEWS, &button, 0)) - new_page = PAGE_NEWS; - box.VSplitLeft(30.0f, 0, &box); + Box.VSplitLeft(90.0f, &Button, &Box); + static int s_NewsButton=0; + if (DoButton_MenuTab(&s_NewsButton, Localize("News"), m_ActivePage==PAGE_NEWS, &Button, 0)) + NewPage = PAGE_NEWS; + Box.VSplitLeft(30.0f, 0, &Box); } - box.VSplitLeft(100.0f, &button, &box); - static int internet_button=0; - if(DoButton_MenuTab(&internet_button, localize("Internet"), active_page==PAGE_INTERNET, &button, CUI::CORNER_TL)) + Box.VSplitLeft(100.0f, &Button, &Box); + static int s_InternetButton=0; + if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), m_ActivePage==PAGE_INTERNET, &Button, CUI::CORNER_TL)) { - client_serverbrowse_refresh(BROWSETYPE_INTERNET); - new_page = PAGE_INTERNET; + ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); + NewPage = PAGE_INTERNET; } - //box.VSplitLeft(4.0f, 0, &box); - box.VSplitLeft(80.0f, &button, &box); - static int lan_button=0; - if(DoButton_MenuTab(&lan_button, localize("LAN"), active_page==PAGE_LAN, &button, 0)) + //Box.VSplitLeft(4.0f, 0, &Box); + Box.VSplitLeft(80.0f, &Button, &Box); + static int s_LanButton=0; + if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), m_ActivePage==PAGE_LAN, &Button, 0)) { - client_serverbrowse_refresh(BROWSETYPE_LAN); - new_page = PAGE_LAN; + ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN); + NewPage = PAGE_LAN; } //box.VSplitLeft(4.0f, 0, &box); - box.VSplitLeft(110.0f, &button, &box); - static int favorites_button=0; - if(DoButton_MenuTab(&favorites_button, localize("Favorites"), active_page==PAGE_FAVORITES, &button, CUI::CORNER_TR)) + Box.VSplitLeft(110.0f, &Button, &Box); + static int s_FavoritesButton=0; + if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR)) { - client_serverbrowse_refresh(BROWSETYPE_FAVORITES); - new_page = PAGE_FAVORITES; + ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); + NewPage = PAGE_FAVORITES; } - box.VSplitLeft(4.0f*5, 0, &box); - box.VSplitLeft(100.0f, &button, &box); - static int demos_button=0; - if(DoButton_MenuTab(&demos_button, localize("Demos"), active_page==PAGE_DEMOS, &button, 0)) + Box.VSplitLeft(4.0f*5, 0, &Box); + Box.VSplitLeft(100.0f, &Button, &Box); + static int s_DemosButton=0; + if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T)) { - demolist_populate(); - new_page = PAGE_DEMOS; + DemolistPopulate(); + NewPage = PAGE_DEMOS; } } else { - /* online menus */ - box.VSplitLeft(90.0f, &button, &box); - static int game_button=0; - if(DoButton_MenuTab(&game_button, localize("Game"), active_page==PAGE_GAME, &button, 0)) - new_page = PAGE_GAME; - - box.VSplitLeft(4.0f, 0, &box); - box.VSplitLeft(140.0f, &button, &box); - static int server_info_button=0; - if(DoButton_MenuTab(&server_info_button, localize("Server info"), active_page==PAGE_SERVER_INFO, &button, 0)) - new_page = PAGE_SERVER_INFO; - - box.VSplitLeft(4.0f, 0, &box); - box.VSplitLeft(140.0f, &button, &box); - static int callvote_button=0; - if(DoButton_MenuTab(&callvote_button, localize("Call vote"), active_page==PAGE_CALLVOTE, &button, 0)) - new_page = PAGE_CALLVOTE; + // online menus + Box.VSplitLeft(90.0f, &Button, &Box); + static int s_GameButton=0; + if(DoButton_MenuTab(&s_GameButton, Localize("Game"), m_ActivePage==PAGE_GAME, &Button, CUI::CORNER_T)) + NewPage = PAGE_GAME; + + Box.VSplitLeft(4.0f, 0, &Box); + Box.VSplitLeft(140.0f, &Button, &Box); + static int s_ServerInfoButton=0; + if(DoButton_MenuTab(&s_ServerInfoButton, Localize("Server info"), m_ActivePage==PAGE_SERVER_INFO, &Button, CUI::CORNER_T)) + NewPage = PAGE_SERVER_INFO; + + Box.VSplitLeft(4.0f, 0, &Box); + Box.VSplitLeft(140.0f, &Button, &Box); + static int s_CallVoteButton=0; + if(DoButton_MenuTab(&s_CallVoteButton, Localize("Call vote"), m_ActivePage==PAGE_CALLVOTE, &Button, CUI::CORNER_T)) + NewPage = PAGE_CALLVOTE; - box.VSplitLeft(30.0f, 0, &box); + Box.VSplitLeft(30.0f, 0, &Box); } /* box.VSplitRight(110.0f, &box, &button); static int system_button=0; - if (UI()->DoButton(&system_button, "System", config.ui_page==PAGE_SYSTEM, &button)) - config.ui_page = PAGE_SYSTEM; + if (UI()->DoButton(&system_button, "System", g_Config.m_UiPage==PAGE_SYSTEM, &button)) + g_Config.m_UiPage = PAGE_SYSTEM; box.VSplitRight(30.0f, &box, 0); */ - box.VSplitRight(90.0f, &box, &button); - static int quit_button=0; - if(DoButton_MenuTab(&quit_button, localize("Quit"), 0, &button, 0)) - popup = POPUP_QUIT; - - box.VSplitRight(10.0f, &box, &button); - box.VSplitRight(130.0f, &box, &button); - static int settings_button=0; - if(DoButton_MenuTab(&settings_button, localize("Settings"), active_page==PAGE_SETTINGS, &button, 0)) - new_page = PAGE_SETTINGS; + Box.VSplitRight(90.0f, &Box, &Button); + static int s_QuitButton=0; + if(DoButton_MenuTab(&s_QuitButton, Localize("Quit"), 0, &Button, CUI::CORNER_T)) + m_Popup = POPUP_QUIT; + + Box.VSplitRight(10.0f, &Box, &Button); + Box.VSplitRight(130.0f, &Box, &Button); + static int s_SettingsButton=0; + if(DoButton_MenuTab(&s_SettingsButton, Localize("Settings"), m_ActivePage==PAGE_SETTINGS, &Button, CUI::CORNER_T)) + NewPage = PAGE_SETTINGS; - if(new_page != -1) + if(NewPage != -1) { - if(client_state() == CLIENTSTATE_OFFLINE) - config.ui_page = new_page; + if(Client()->State() == IClient::STATE_OFFLINE) + g_Config.m_UiPage = NewPage; else - game_page = new_page; + m_GamePage = NewPage; } return 0; } -void MENUS::render_loading(float percent) +void CMenus::RenderLoading(float Percent) { - static int64 last_load_render = 0; + static int64 LastLoadRender = 0; // make sure that we don't render for each little thing we load // because that will slow down loading if we have vsync - if(time_get()-last_load_render < time_freq()/60) + if(time_get()-LastLoadRender < time_freq()/60) return; - last_load_render = time_get(); + LastLoadRender = time_get(); // need up date this here to get correct - vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f)); - gui_color = vec4(rgb.r, rgb.g, rgb.b, config.ui_color_alpha/255.0f); + vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f)); + ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f); - CUIRect screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); + CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); - render_background(); + RenderBackground(); float tw; float w = 700; float h = 200; - float x = screen.w/2-w/2; - float y = screen.h/2-h/2; + float x = Screen.w/2-w/2; + float y = Screen.h/2-h/2; Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.50f); - RenderTools()->draw_round_rect(x, y, w, h, 40.0f); + RenderTools()->DrawRoundRect(x, y, w, h, 40.0f); Graphics()->QuadsEnd(); - const char *caption = localize("Loading"); + const char *pCaption = Localize("Loading"); - tw = gfx_text_width(0, 48.0f, caption, -1); + tw = TextRender()->TextWidth(0, 48.0f, pCaption, -1); CUIRect r; r.x = x; r.y = y+20; r.w = w; r.h = h; - UI()->DoLabel(&r, caption, 48.0f, 0, -1); + UI()->DoLabel(&r, pCaption, 48.0f, 0, -1); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,0.75f); - RenderTools()->draw_round_rect(x+40, y+h-75, (w-80)*percent, 25, 5.0f); + RenderTools()->DrawRoundRect(x+40, y+h-75, (w-80)*Percent, 25, 5.0f); Graphics()->QuadsEnd(); - gfx_swap(); + Graphics()->Swap(); } -void MENUS::render_news(CUIRect main_view) +void CMenus::RenderNews(CUIRect MainView) { - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); } -void MENUS::on_init() +void CMenus::OnInit() { /* @@ -669,261 +678,263 @@ void MENUS::on_init() exit(-1); // */ - if(config.cl_show_welcome) - popup = POPUP_FIRST_LAUNCH; - config.cl_show_welcome = 0; + if(g_Config.m_ClShowWelcome) + m_Popup = POPUP_FIRST_LAUNCH; + g_Config.m_ClShowWelcome = 0; } -void MENUS::popup_message(const char *topic, const char *body, const char *button) +void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton) { - str_copy(message_topic, topic, sizeof(message_topic)); - str_copy(message_body, body, sizeof(message_body)); - str_copy(message_button, button, sizeof(message_button)); - popup = POPUP_MESSAGE; + str_copy(m_aMessageTopic, pTopic, sizeof(m_aMessageTopic)); + str_copy(m_aMessageBody, pBody, sizeof(m_aMessageBody)); + str_copy(m_aMessageButton, pButton, sizeof(m_aMessageButton)); + m_Popup = POPUP_MESSAGE; } -int MENUS::render() +int CMenus::Render() { - CUIRect screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); + CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); - static bool first = true; - if(first) + static bool s_First = true; + if(s_First) { - if(config.ui_page == PAGE_INTERNET) - client_serverbrowse_refresh(0); - else if(config.ui_page == PAGE_LAN) - client_serverbrowse_refresh(1); - first = false; + if(g_Config.m_UiPage == PAGE_INTERNET) + ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); + else if(g_Config.m_UiPage == PAGE_LAN) + ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN); + else if(g_Config.m_UiPage == PAGE_FAVORITES) + ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); + s_First = false; } - if(client_state() == CLIENTSTATE_ONLINE) + if(Client()->State() == IClient::STATE_ONLINE) { - color_tabbar_inactive = color_tabbar_inactive_ingame; - color_tabbar_active = color_tabbar_active_ingame; + ms_ColorTabbarInactive = ms_ColorTabbarInactiveIngame; + ms_ColorTabbarActive = ms_ColorTabbarActiveIngame; } else { - render_background(); - color_tabbar_inactive = color_tabbar_inactive_outgame; - color_tabbar_active = color_tabbar_active_outgame; + RenderBackground(); + ms_ColorTabbarInactive = ms_ColorTabbarInactiveOutgame; + ms_ColorTabbarActive = ms_ColorTabbarActiveOutgame; } - CUIRect tab_bar; - CUIRect main_view; + CUIRect TabBar; + CUIRect MainView; // some margin around the screen - screen.Margin(10.0f, &screen); + Screen.Margin(10.0f, &Screen); - if(popup == POPUP_NONE) + if(m_Popup == POPUP_NONE) { // do tab bar - screen.HSplitTop(24.0f, &tab_bar, &main_view); - tab_bar.VMargin(20.0f, &tab_bar); - render_menubar(tab_bar); + Screen.HSplitTop(24.0f, &TabBar, &MainView); + TabBar.VMargin(20.0f, &TabBar); + RenderMenubar(TabBar); // news is not implemented yet - if(config.ui_page <= PAGE_NEWS || config.ui_page > PAGE_SETTINGS || (client_state() == CLIENTSTATE_OFFLINE && config.ui_page >= PAGE_GAME && config.ui_page <= PAGE_CALLVOTE)) + if(g_Config.m_UiPage <= PAGE_NEWS || g_Config.m_UiPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiPage >= PAGE_GAME && g_Config.m_UiPage <= PAGE_CALLVOTE)) { - client_serverbrowse_refresh(BROWSETYPE_INTERNET); - config.ui_page = PAGE_INTERNET; + ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); + g_Config.m_UiPage = PAGE_INTERNET; } // render current page - if(client_state() != CLIENTSTATE_OFFLINE) + if(Client()->State() != IClient::STATE_OFFLINE) { - if(game_page == PAGE_GAME) - render_game(main_view); - else if(game_page == PAGE_SERVER_INFO) - render_serverinfo(main_view); - else if(game_page == PAGE_CALLVOTE) - render_servercontrol(main_view); - else if(game_page == PAGE_SETTINGS) - render_settings(main_view); + if(m_GamePage == PAGE_GAME) + RenderGame(MainView); + else if(m_GamePage == PAGE_SERVER_INFO) + RenderServerInfo(MainView); + else if(m_GamePage == PAGE_CALLVOTE) + RenderServerControl(MainView); + else if(m_GamePage == PAGE_SETTINGS) + RenderSettings(MainView); } - else if(config.ui_page == PAGE_NEWS) - render_news(main_view); - else if(config.ui_page == PAGE_INTERNET) - render_serverbrowser(main_view); - else if(config.ui_page == PAGE_LAN) - render_serverbrowser(main_view); - else if(config.ui_page == PAGE_DEMOS) - render_demolist(main_view); - else if(config.ui_page == PAGE_FAVORITES) - render_serverbrowser(main_view); - else if(config.ui_page == PAGE_SETTINGS) - render_settings(main_view); + else if(g_Config.m_UiPage == PAGE_NEWS) + RenderNews(MainView); + else if(g_Config.m_UiPage == PAGE_INTERNET) + RenderServerbrowser(MainView); + else if(g_Config.m_UiPage == PAGE_LAN) + RenderServerbrowser(MainView); + else if(g_Config.m_UiPage == PAGE_DEMOS) + RenderDemoList(MainView); + else if(g_Config.m_UiPage == PAGE_FAVORITES) + RenderServerbrowser(MainView); + else if(g_Config.m_UiPage == PAGE_SETTINGS) + RenderSettings(MainView); } else { // make sure that other windows doesn't do anything funnay! //UI()->SetHotItem(0); //UI()->SetActiveItem(0); - char buf[128]; - const char *title = ""; - const char *extra_text = ""; - const char *button_text = ""; - int extra_align = 0; + char aBuf[128]; + const char *pTitle = ""; + const char *pExtraText = ""; + const char *pButtonText = ""; + int ExtraAlign = 0; - if(popup == POPUP_MESSAGE) + if(m_Popup == POPUP_MESSAGE) { - title = message_topic; - extra_text = message_body; - button_text = message_button; + pTitle = m_aMessageTopic; + pExtraText = m_aMessageBody; + pButtonText = m_aMessageButton; } - else if(popup == POPUP_CONNECTING) + else if(m_Popup == POPUP_CONNECTING) { - title = localize("Connecting to"); - extra_text = config.ui_server_address; // TODO: query the client about the address - button_text = localize("Abort"); - if(client_mapdownload_totalsize() > 0) + pTitle = Localize("Connecting to"); + pExtraText = g_Config.m_UiServerAddress; // TODO: query the client about the address + pButtonText = Localize("Abort"); + if(Client()->MapDownloadTotalsize() > 0) { - title = localize("Downloading map"); - str_format(buf, sizeof(buf), "%d/%d KiB", client_mapdownload_amount()/1024, client_mapdownload_totalsize()/1024); - extra_text = buf; + pTitle = Localize("Downloading map"); + str_format(aBuf, sizeof(aBuf), "%d/%d KiB", Client()->MapDownloadAmount()/1024, Client()->MapDownloadTotalsize()/1024); + pExtraText = aBuf; } } - else if(popup == POPUP_DISCONNECTED) + else if(m_Popup == POPUP_DISCONNECTED) { - title = localize("Disconnected"); - extra_text = client_error_string(); - button_text = localize("Ok"); - extra_align = -1; + pTitle = Localize("Disconnected"); + pExtraText = Client()->ErrorString(); + pButtonText = Localize("Ok"); + ExtraAlign = -1; } - else if(popup == POPUP_PURE) + else if(m_Popup == POPUP_PURE) { - title = localize("Disconnected"); - extra_text = localize("The server is running a non-standard tuning on a pure game type."); - button_text = localize("Ok"); - extra_align = -1; + pTitle = Localize("Disconnected"); + pExtraText = Localize("The server is running a non-standard tuning on a pure game type."); + pButtonText = Localize("Ok"); + ExtraAlign = -1; } - else if(popup == POPUP_PASSWORD) + else if(m_Popup == POPUP_PASSWORD) { - title = localize("Password Incorrect"); - extra_text = client_error_string(); - button_text = localize("Try again"); + pTitle = Localize("Password Incorrect"); + pExtraText = Client()->ErrorString(); + pButtonText = Localize("Try again"); } - else if(popup == POPUP_QUIT) + else if(m_Popup == POPUP_QUIT) { - title = localize("Quit"); - extra_text = localize("Are you sure that you want to quit?"); + pTitle = Localize("Quit"); + pExtraText = Localize("Are you sure that you want to quit?"); } - else if(popup == POPUP_FIRST_LAUNCH) + else if(m_Popup == POPUP_FIRST_LAUNCH) { - title = localize("Welcome to Teeworlds"); - extra_text = localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server."); - button_text = localize("Ok"); - extra_align = -1; + pTitle = Localize("Welcome to Teeworlds"); + pExtraText = Localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server."); + pButtonText = Localize("Ok"); + ExtraAlign = -1; } - CUIRect box, part; - box = screen; - box.VMargin(150.0f, &box); - box.HMargin(150.0f, &box); + CUIRect Box, Part; + Box = Screen; + Box.VMargin(150.0f, &Box); + Box.HMargin(150.0f, &Box); // render the box - RenderTools()->DrawUIRect(&box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f); + RenderTools()->DrawUIRect(&Box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f); - box.HSplitTop(20.f, &part, &box); - box.HSplitTop(24.f, &part, &box); - UI()->DoLabel(&part, title, 24.f, 0); - box.HSplitTop(20.f, &part, &box); - box.HSplitTop(24.f, &part, &box); - part.VMargin(20.f, &part); + Box.HSplitTop(20.f, &Part, &Box); + Box.HSplitTop(24.f, &Part, &Box); + UI()->DoLabel(&Part, pTitle, 24.f, 0); + Box.HSplitTop(20.f, &Part, &Box); + Box.HSplitTop(24.f, &Part, &Box); + Part.VMargin(20.f, &Part); - if(extra_align == -1) - UI()->DoLabel(&part, extra_text, 20.f, -1, (int)part.w); + if(ExtraAlign == -1) + UI()->DoLabel(&Part, pExtraText, 20.f, -1, (int)Part.w); else - UI()->DoLabel(&part, extra_text, 20.f, 0, -1); + UI()->DoLabel(&Part, pExtraText, 20.f, 0, -1); - if(popup == POPUP_QUIT) + if(m_Popup == POPUP_QUIT) { - CUIRect yes, no; - box.HSplitBottom(20.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); - part.VMargin(80.0f, &part); + CUIRect Yes, No; + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Part.VMargin(80.0f, &Part); - part.VSplitMid(&no, &yes); + Part.VSplitMid(&No, &Yes); - yes.VMargin(20.0f, &yes); - no.VMargin(20.0f, &no); + Yes.VMargin(20.0f, &Yes); + No.VMargin(20.0f, &No); - static int button_abort = 0; - if(DoButton_Menu(&button_abort, localize("No"), 0, &no) || escape_pressed) - popup = POPUP_NONE; + static int s_ButtonAbort = 0; + if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed) + m_Popup = POPUP_NONE; - static int button_tryagain = 0; - if(DoButton_Menu(&button_tryagain, localize("Yes"), 0, &yes) || enter_pressed) - client_quit(); + static int s_ButtonTryAgain = 0; + if(DoButton_Menu(&s_ButtonTryAgain, Localize("Yes"), 0, &Yes) || m_EnterPressed) + Client()->Quit(); } - else if(popup == POPUP_PASSWORD) + else if(m_Popup == POPUP_PASSWORD) { - CUIRect label, textbox, tryagain, abort; + CUIRect Label, TextBox, TryAgain, Abort; - box.HSplitBottom(20.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); - part.VMargin(80.0f, &part); + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Part.VMargin(80.0f, &Part); - part.VSplitMid(&abort, &tryagain); + Part.VSplitMid(&Abort, &TryAgain); - tryagain.VMargin(20.0f, &tryagain); - abort.VMargin(20.0f, &abort); + TryAgain.VMargin(20.0f, &TryAgain); + Abort.VMargin(20.0f, &Abort); - static int button_abort = 0; - if(DoButton_Menu(&button_abort, localize("Abort"), 0, &abort) || escape_pressed) - popup = POPUP_NONE; + static int s_ButtonAbort = 0; + if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed) + m_Popup = POPUP_NONE; - static int button_tryagain = 0; - if(DoButton_Menu(&button_tryagain, localize("Try again"), 0, &tryagain) || enter_pressed) + static int s_ButtonTryAgain = 0; + if(DoButton_Menu(&s_ButtonTryAgain, Localize("Try again"), 0, &TryAgain) || m_EnterPressed) { - client_connect(config.ui_server_address); + Client()->Connect(g_Config.m_UiServerAddress); } - box.HSplitBottom(60.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); + Box.HSplitBottom(60.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); - part.VSplitLeft(60.0f, 0, &label); - label.VSplitLeft(100.0f, 0, &textbox); - textbox.VSplitLeft(20.0f, 0, &textbox); - textbox.VSplitRight(60.0f, &textbox, 0); - UI()->DoLabel(&label, localize("Password"), 20, -1); - DoEditBox(&config.password, &textbox, config.password, sizeof(config.password), 14.0f, true); + Part.VSplitLeft(60.0f, 0, &Label); + Label.VSplitLeft(100.0f, 0, &TextBox); + TextBox.VSplitLeft(20.0f, 0, &TextBox); + TextBox.VSplitRight(60.0f, &TextBox, 0); + UI()->DoLabel(&Label, Localize("Password"), 18.0f, -1); + DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, true); } - else if(popup == POPUP_FIRST_LAUNCH) + else if(m_Popup == POPUP_FIRST_LAUNCH) { - CUIRect label, textbox; + CUIRect Label, TextBox; - box.HSplitBottom(20.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); - part.VMargin(80.0f, &part); + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Part.VMargin(80.0f, &Part); - static int enter_button = 0; - if(DoButton_Menu(&enter_button, localize("Enter"), 0, &part) || enter_pressed) - popup = POPUP_NONE; + static int s_EnterButton = 0; + if(DoButton_Menu(&s_EnterButton, Localize("Enter"), 0, &Part) || m_EnterPressed) + m_Popup = POPUP_NONE; - box.HSplitBottom(40.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); + Box.HSplitBottom(40.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); - part.VSplitLeft(60.0f, 0, &label); - label.VSplitLeft(100.0f, 0, &textbox); - textbox.VSplitLeft(20.0f, 0, &textbox); - textbox.VSplitRight(60.0f, &textbox, 0); - UI()->DoLabel(&label, localize("Nickname"), 20, -1); - DoEditBox(&config.player_name, &textbox, config.player_name, sizeof(config.player_name), 14.0f); + Part.VSplitLeft(60.0f, 0, &Label); + Label.VSplitLeft(100.0f, 0, &TextBox); + TextBox.VSplitLeft(20.0f, 0, &TextBox); + TextBox.VSplitRight(60.0f, &TextBox, 0); + UI()->DoLabel(&Label, Localize("Nickname"), 18.0f, -1); + DoEditBox(&g_Config.m_PlayerName, &TextBox, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 12.0f); } else { - box.HSplitBottom(20.f, &box, &part); - box.HSplitBottom(24.f, &box, &part); - part.VMargin(120.0f, &part); + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Part.VMargin(120.0f, &Part); - static int button = 0; - if(DoButton_Menu(&button, button_text, 0, &part) || escape_pressed || enter_pressed) + static int s_Button = 0; + if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed) { - if(popup == POPUP_CONNECTING) - client_disconnect(); - popup = POPUP_NONE; + if(m_Popup == POPUP_CONNECTING) + Client()->Disconnect(); + m_Popup = POPUP_NONE; } } } @@ -932,109 +943,113 @@ int MENUS::render() } -void MENUS::set_active(bool active) +void CMenus::SetActive(bool Active) { - menu_active = active; - if(!menu_active && need_sendinfo) + m_MenuActive = Active; + if(!m_MenuActive && m_NeedSendinfo) { - gameclient.send_info(false); - need_sendinfo = false; + m_pClient->SendInfo(false); + m_NeedSendinfo = false; } } -void MENUS::on_reset() +void CMenus::OnReset() { } -bool MENUS::on_mousemove(float x, float y) +bool CMenus::OnMouseMove(float x, float y) { - last_input = time_get(); + m_LastInput = time_get(); - if(!menu_active) + if(!m_MenuActive) return false; - mouse_pos.x += x; - mouse_pos.y += y; - if(mouse_pos.x < 0) mouse_pos.x = 0; - if(mouse_pos.y < 0) mouse_pos.y = 0; - if(mouse_pos.x > Graphics()->ScreenWidth()) mouse_pos.x = Graphics()->ScreenWidth(); - if(mouse_pos.y > Graphics()->ScreenHeight()) mouse_pos.y = Graphics()->ScreenHeight(); + m_MousePos.x += x; + m_MousePos.y += y; + if(m_MousePos.x < 0) m_MousePos.x = 0; + if(m_MousePos.y < 0) m_MousePos.y = 0; + if(m_MousePos.x > Graphics()->ScreenWidth()) m_MousePos.x = Graphics()->ScreenWidth(); + if(m_MousePos.y > Graphics()->ScreenHeight()) m_MousePos.y = Graphics()->ScreenHeight(); return true; } -bool MENUS::on_input(INPUT_EVENT e) +bool CMenus::OnInput(IInput::CEvent e) { - last_input = time_get(); + m_LastInput = time_get(); // special handle esc and enter for popup purposes - if(e.flags&INPFLAG_PRESS) + if(e.m_Flags&IInput::FLAG_PRESS) { - if(e.key == KEY_ESCAPE) + if(e.m_Key == KEY_ESCAPE) { - escape_pressed = true; - set_active(!is_active()); + m_EscapePressed = true; + SetActive(!IsActive()); return true; } } - if(is_active()) + if(IsActive()) { // special for popups - if(e.flags&INPFLAG_PRESS && e.key == KEY_RETURN) - enter_pressed = true; + if(e.m_Flags&IInput::FLAG_PRESS && e.m_Key == KEY_RETURN) + m_EnterPressed = true; - if(num_inputevents < MAX_INPUTEVENTS) - inputevents[num_inputevents++] = e; + if(m_NumInputEvents < MAX_INPUTEVENTS) + m_aInputEvents[m_NumInputEvents++] = e; return true; } return false; } -void MENUS::on_statechange(int new_state, int old_state) +void CMenus::OnStateChange(int NewState, int OldState) { - if(new_state == CLIENTSTATE_OFFLINE) + // reset active item + UI()->SetActiveItem(0); + + if(NewState == IClient::STATE_OFFLINE) { - popup = POPUP_NONE; - if(client_error_string() && client_error_string()[0] != 0) + m_Popup = POPUP_NONE; + if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) { - if(strstr(client_error_string(), "password")) + if(str_find(Client()->ErrorString(), "password")) { - popup = POPUP_PASSWORD; - UI()->SetHotItem(&config.password); - UI()->SetActiveItem(&config.password); + m_Popup = POPUP_PASSWORD; + UI()->SetHotItem(&g_Config.m_Password); + UI()->SetActiveItem(&g_Config.m_Password); } else - popup = POPUP_DISCONNECTED; - } } - else if(new_state == CLIENTSTATE_LOADING) + m_Popup = POPUP_DISCONNECTED; + } + } + else if(NewState == IClient::STATE_LOADING) { - popup = POPUP_CONNECTING; - client_serverinfo_request(); + m_Popup = POPUP_CONNECTING; + //client_serverinfo_request(); } - else if(new_state == CLIENTSTATE_CONNECTING) - popup = POPUP_CONNECTING; - else if (new_state == CLIENTSTATE_ONLINE || new_state == CLIENTSTATE_DEMOPLAYBACK) + else if(NewState == IClient::STATE_CONNECTING) + m_Popup = POPUP_CONNECTING; + else if (NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK) { - popup = POPUP_NONE; - set_active(false); + m_Popup = POPUP_NONE; + SetActive(false); } } extern "C" void font_debug_render(); -void MENUS::on_render() +void CMenus::OnRender() { /* // text rendering test stuff render_background(); - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, 10, 10, 20, TEXTFLAG_RENDER); - gfx_text_ex(&cursor, "ようこそ - ガイド", -1); + CTextCursor cursor; + TextRender()->SetCursor(&cursor, 10, 10, 20, TEXTFLAG_RENDER); + TextRender()->TextEx(&cursor, "ようこそ - ガイド", -1); - gfx_text_set_cursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER); - gfx_text_ex(&cursor, "ようこそ - ガイド", -1); + TextRender()->SetCursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER); + TextRender()->TextEx(&cursor, "ようこそ - ガイド", -1); //Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); @@ -1042,101 +1057,105 @@ void MENUS::on_render() Graphics()->QuadsEnd(); return;*/ - if(client_state() != CLIENTSTATE_ONLINE && client_state() != CLIENTSTATE_DEMOPLAYBACK) - set_active(true); + if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK) + SetActive(true); - if(client_state() == CLIENTSTATE_DEMOPLAYBACK) + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { - CUIRect screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); - render_demoplayer(screen); + CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); + RenderDemoPlayer(Screen); } - if(client_state() == CLIENTSTATE_ONLINE && gameclient.servermode == gameclient.SERVERMODE_PUREMOD) + if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_ServerMode == m_pClient->SERVERMODE_PUREMOD) { - client_disconnect(); - set_active(true); - popup = POPUP_PURE; + Client()->Disconnect(); + SetActive(true); + m_Popup = POPUP_PURE; } - if(!is_active()) + if(!IsActive()) { - escape_pressed = false; - enter_pressed = false; - num_inputevents = 0; + m_EscapePressed = false; + m_EnterPressed = false; + m_NumInputEvents = 0; return; } // update colors - vec3 rgb = hsl_to_rgb(vec3(config.ui_color_hue/255.0f, config.ui_color_sat/255.0f, config.ui_color_lht/255.0f)); - gui_color = vec4(rgb.r, rgb.g, rgb.b, config.ui_color_alpha/255.0f); - - color_tabbar_inactive_outgame = vec4(0,0,0,0.25f); - color_tabbar_active_outgame = vec4(0,0,0,0.5f); - - float color_ingame_scale_i = 0.5f; - float color_ingame_scale_a = 0.2f; - color_tabbar_inactive_ingame = vec4( - gui_color.r*color_ingame_scale_i, - gui_color.g*color_ingame_scale_i, - gui_color.b*color_ingame_scale_i, - gui_color.a*0.8f); + vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f)); + ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f); + + ms_ColorTabbarInactiveOutgame = vec4(0,0,0,0.25f); + ms_ColorTabbarActiveOutgame = vec4(0,0,0,0.5f); + + float ColorIngameScaleI = 0.5f; + float ColorIngameAcaleA = 0.2f; + ms_ColorTabbarInactiveIngame = vec4( + ms_GuiColor.r*ColorIngameScaleI, + ms_GuiColor.g*ColorIngameScaleI, + ms_GuiColor.b*ColorIngameScaleI, + ms_GuiColor.a*0.8f); - color_tabbar_active_ingame = vec4( - gui_color.r*color_ingame_scale_a, - gui_color.g*color_ingame_scale_a, - gui_color.b*color_ingame_scale_a, - gui_color.a); + ms_ColorTabbarActiveIngame = vec4( + ms_GuiColor.r*ColorIngameAcaleA, + ms_GuiColor.g*ColorIngameAcaleA, + ms_GuiColor.b*ColorIngameAcaleA, + ms_GuiColor.a); // update the ui - CUIRect *screen = UI()->Screen(); - float mx = (mouse_pos.x/(float)Graphics()->ScreenWidth())*screen->w; - float my = (mouse_pos.y/(float)Graphics()->ScreenHeight())*screen->h; + CUIRect *pScreen = UI()->Screen(); + float mx = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w; + float my = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h; - int buttons = 0; - if(inp_key_pressed(KEY_MOUSE_1)) buttons |= 1; - if(inp_key_pressed(KEY_MOUSE_2)) buttons |= 2; - if(inp_key_pressed(KEY_MOUSE_3)) buttons |= 4; + int Buttons = 0; + if(m_UseMouseButtons) + { + if(Input()->KeyPressed(KEY_MOUSE_1)) Buttons |= 1; + if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2; + if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4; + } - UI()->Update(mx,my,mx*3.0f,my*3.0f,buttons); + UI()->Update(mx,my,mx*3.0f,my*3.0f,Buttons); // render - if(client_state() != CLIENTSTATE_DEMOPLAYBACK) - render(); + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + Render(); // render cursor - Graphics()->TextureSet(data->images[IMAGE_CURSOR].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); - Graphics()->QuadsDrawTL(mx,my,24,24); + IGraphics::CQuadItem QuadItem(mx, my, 24, 24); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // render debug information - if(config.debug) + if(g_Config.m_Debug) { - CUIRect screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h); - - char buf[512]; - str_format(buf, sizeof(buf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem()); - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, 10, 10, 10, TEXTFLAG_RENDER); - gfx_text_ex(&cursor, buf, -1); + CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); + + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem()); + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, 10, 10, 10, TEXTFLAG_RENDER); + TextRender()->TextEx(&Cursor, aBuf, -1); } - escape_pressed = false; - enter_pressed = false; - num_inputevents = 0; + m_EscapePressed = false; + m_EnterPressed = false; + m_NumInputEvents = 0; } -static int texture_blob = -1; +static int gs_TextureBlob = -1; -void MENUS::render_background() +void CMenus::RenderBackground() { //Graphics()->Clear(1,1,1); //render_sunrays(0,0); - if(texture_blob == -1) - texture_blob = Graphics()->LoadTexture("blob.png", IMG_AUTO, 0); + if(gs_TextureBlob == -1) + gs_TextureBlob = Graphics()->LoadTexture("blob.png", CImageInfo::FORMAT_AUTO, 0); float sw = 300*Graphics()->ScreenAspect(); @@ -1150,36 +1169,41 @@ void MENUS::render_background() Graphics()->QuadsBegin(); //vec4 bottom(gui_color.r*0.3f, gui_color.g*0.3f, gui_color.b*0.3f, 1.0f); //vec4 bottom(0, 0, 0, 1.0f); - vec4 bottom(gui_color.r, gui_color.g, gui_color.b, 1.0f); - vec4 top(gui_color.r, gui_color.g, gui_color.b, 1.0f); - Graphics()->SetColorVertex(0, top.r, top.g, top.b, top.a); - Graphics()->SetColorVertex(1, top.r, top.g, top.b, top.a); - Graphics()->SetColorVertex(2, bottom.r, bottom.g, bottom.b, bottom.a); - Graphics()->SetColorVertex(3, bottom.r, bottom.g, bottom.b, bottom.a); - Graphics()->QuadsDrawTL(0, 0, sw, sh); + vec4 Bottom(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f); + vec4 Top(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a), + IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a), + IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a)}; + Graphics()->SetColorVertex(Array, 4); + IGraphics::CQuadItem QuadItem(0, 0, sw, sh); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // render the tiles Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - float size = 15.0f; - float offset_time = fmod(client_localtime()*0.15f, 2.0f); - for(int y = -2; y < (int)(sw/size); y++) - for(int x = -2; x < (int)(sh/size); x++) + float Size = 15.0f; + float OffsetTime = fmod(Client()->LocalTime()*0.15f, 2.0f); + for(int y = -2; y < (int)(sw/Size); y++) + for(int x = -2; x < (int)(sh/Size); x++) { Graphics()->SetColor(0,0,0,0.045f); - Graphics()->QuadsDrawTL((x-offset_time)*size*2+(y&1)*size, (y+offset_time)*size, size, size); + IGraphics::CQuadItem QuadItem((x-OffsetTime)*Size*2+(y&1)*Size, (y+OffsetTime)*Size, Size, Size); + Graphics()->QuadsDrawTL(&QuadItem, 1); } Graphics()->QuadsEnd(); // render border fade - Graphics()->TextureSet(texture_blob); + Graphics()->TextureSet(gs_TextureBlob); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - Graphics()->QuadsDrawTL(-100, -100, sw+200, sh+200); + QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); // restore screen - {CUIRect screen = *UI()->Screen(); - Graphics()->MapScreen(screen.x, screen.y, screen.w, screen.h);} + {CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);} } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h new file mode 100644 index 00000000..3055e661 --- /dev/null +++ b/src/game/client/components/menus.h @@ -0,0 +1,223 @@ +#ifndef GAME_CLIENT_COMPONENTS_MENUS_H +#define GAME_CLIENT_COMPONENTS_MENUS_H + +#include <base/vmath.h> +#include <base/tl/sorted_array.h> + +#include <game/client/component.h> +#include <game/client/ui.h> + + +// compnent to fetch keypresses, override all other input +class CMenusKeyBinder : public CComponent +{ +public: + bool m_TakeKey; + bool m_GotKey; + IInput::CEvent m_Key; + CMenusKeyBinder(); + virtual bool OnInput(IInput::CEvent Event); +}; + +class CMenus : public CComponent +{ + static vec4 ms_GuiColor; + static vec4 ms_ColorTabbarInactiveOutgame; + static vec4 ms_ColorTabbarActiveOutgame; + static vec4 ms_ColorTabbarInactiveIngame; + static vec4 ms_ColorTabbarActiveIngame; + static vec4 ms_ColorTabbarInactive; + static vec4 ms_ColorTabbarActive; + + vec4 ButtonColorMul(const void *pID); + + + int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); + int DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + + int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect); + int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + + /*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + */ + + int DoButton_BrowseIcon(int Checked, const CUIRect *pRect); + int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + + //static void ui_draw_browse_icon(int what, const CUIRect *r); + //static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + + /*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra); + static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); + */ + int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false, int Corners=CUI::CORNER_ALL); + //static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false); + + float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current); + float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current); + void DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + int DoKeyReader(void *pID, const CUIRect *pRect, int Key); + + //static int ui_do_key_reader(void *id, const CUIRect *rect, int key); + void UiDoGetButtons(int Start, int Stop, CUIRect View); + + struct CListboxItem + { + int m_Visible; + int m_Selected; + CUIRect m_Rect; + CUIRect m_HitRect; + }; + + void UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue); + CListboxItem UiDoListboxNextItem(void *pID, bool Selected = false); + static CListboxItem UiDoListboxNextRow(); + int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated); + + //static void demolist_listdir_callback(const char *name, int is_dir, void *user); + //static void demolist_list_callback(const CUIRect *rect, int index, void *user); + + enum + { + POPUP_NONE=0, + POPUP_FIRST_LAUNCH, + POPUP_CONNECTING, + POPUP_MESSAGE, + POPUP_DISCONNECTED, + POPUP_PURE, + POPUP_PASSWORD, + POPUP_QUIT, + }; + + enum + { + PAGE_NEWS=1, + PAGE_GAME, + PAGE_SERVER_INFO, + PAGE_CALLVOTE, + PAGE_INTERNET, + PAGE_LAN, + PAGE_FAVORITES, + PAGE_DEMOS, + PAGE_SETTINGS, + PAGE_SYSTEM, + }; + + int m_GamePage; + int m_Popup; + int m_ActivePage; + bool m_MenuActive; + bool m_UseMouseButtons; + vec2 m_MousePos; + + int64 m_LastInput; + + // + char m_aMessageTopic[512]; + char m_aMessageBody[512]; + char m_aMessageButton[512]; + + void PopupMessage(const char *pTopic, const char *pBody, const char *pButton); + + // TODO: this is a bit ugly but.. well.. yeah + enum { MAX_INPUTEVENTS = 32 }; + static IInput::CEvent m_aInputEvents[MAX_INPUTEVENTS]; + static int m_NumInputEvents; + + // some settings + static float ms_ButtonHeight; + static float ms_ListheaderHeight; + static float ms_FontmodHeight; + + // for graphic settings + bool m_NeedRestart; + bool m_NeedSendinfo; + + // + bool m_EscapePressed; + bool m_EnterPressed; + + // for call vote + int m_CallvoteSelectedOption; + int m_CallvoteSelectedPlayer; + + // demo + struct CDemoItem + { + char m_aFilename[512]; + char m_aName[256]; + + bool operator<(const CDemoItem &Other) { return str_comp(m_aName, Other.m_aName) < 0; } + }; + + sorted_array<CDemoItem> m_lDemos; + + void DemolistPopulate(); + static void DemolistCountCallback(const char *pName, int IsDir, void *pUser); + static void DemolistFetchCallback(const char *pName, int IsDir, void *pUser); + + // found in menus.cpp + int Render(); + //void render_background(); + //void render_loading(float percent); + int RenderMenubar(CUIRect r); + void RenderNews(CUIRect MainView); + + // found in menus_demo.cpp + void RenderDemoPlayer(CUIRect MainView); + void RenderDemoList(CUIRect MainView); + + // found in menus_ingame.cpp + void RenderGame(CUIRect MainView); + void RenderServerInfo(CUIRect MainView); + void RenderServerControl(CUIRect MainView); + void RenderServerControlKick(CUIRect MainView); + void RenderServerControlServer(CUIRect MainView); + + // found in menus_browser.cpp + int m_SelectedIndex; + void RenderServerbrowserServerList(CUIRect View); + void RenderServerbrowserServerDetail(CUIRect View); + void RenderServerbrowserFilters(CUIRect View); + void RenderServerbrowser(CUIRect MainView); + + // found in menus_settings.cpp + void RenderSettingsGeneral(CUIRect MainView); + void RenderSettingsPlayer(CUIRect MainView); + void RenderSettingsControls(CUIRect MainView); + void RenderSettingsGraphics(CUIRect MainView); + void RenderSettingsSound(CUIRect MainView); + void RenderSettings(CUIRect MainView); + + void SetActive(bool Active); +public: + void RenderBackground(); + + void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; } + + static CMenusKeyBinder m_Binder; + + CMenus(); + + void RenderLoading(float Percent); + + bool IsActive() const { return m_MenuActive; } + + virtual void OnInit(); + + virtual void OnStateChange(int NewState, int OldState); + virtual void OnReset(); + virtual void OnRender(); + virtual bool OnInput(IInput::CEvent Event); + virtual bool OnMouseMove(float x, float y); +}; +#endif diff --git a/src/game/client/components/menus.hpp b/src/game/client/components/menus.hpp deleted file mode 100644 index 02759403..00000000 --- a/src/game/client/components/menus.hpp +++ /dev/null @@ -1,216 +0,0 @@ -#include <base/vmath.hpp> -#include <base/tl/sorted_array.hpp> - -#include <game/client/component.hpp> -#include <game/client/ui.hpp> - - -// compnent to fetch keypresses, override all other input -class MENUS_KEYBINDER : public COMPONENT -{ -public: - bool take_key; - bool got_key; - INPUT_EVENT key; - MENUS_KEYBINDER(); - virtual bool on_input(INPUT_EVENT e); -}; - -class MENUS : public COMPONENT -{ - static vec4 gui_color; - static vec4 color_tabbar_inactive_outgame; - static vec4 color_tabbar_active_outgame; - static vec4 color_tabbar_inactive_ingame; - static vec4 color_tabbar_active_ingame; - static vec4 color_tabbar_inactive; - static vec4 color_tabbar_active; - - vec4 button_color_mul(const void *pID); - - - int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); - int DoButton_SettingsTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - - int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect); - int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - - /*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - */ - - int DoButton_BrowseIcon(int Checked, const CUIRect *pRect); - int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - int DoButton_ListRow(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - - //static void ui_draw_browse_icon(int what, const CUIRect *r); - //static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - - /*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra); - static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - */ - int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false); - //static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false); - - float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current); - float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current); - int DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect); - int DoKeyReader(void *pID, const CUIRect *pRect, int Key); - - //static int ui_do_key_reader(void *id, const CUIRect *rect, int key); - void ui_do_getbuttons(int start, int stop, CUIRect view); - - struct LISTBOXITEM - { - int visible; - int selected; - CUIRect rect; - CUIRect hitrect; - }; - - void ui_do_listbox_start(void *id, const CUIRect *rect, float row_height, const char *title, int num_items, int selected_index); - LISTBOXITEM ui_do_listbox_nextitem(void *id); - static LISTBOXITEM ui_do_listbox_nextrow(); - int ui_do_listbox_end(); - - //static void demolist_listdir_callback(const char *name, int is_dir, void *user); - //static void demolist_list_callback(const RECT *rect, int index, void *user); - - enum - { - POPUP_NONE=0, - POPUP_FIRST_LAUNCH, - POPUP_CONNECTING, - POPUP_MESSAGE, - POPUP_DISCONNECTED, - POPUP_PURE, - POPUP_PASSWORD, - POPUP_QUIT, - }; - - enum - { - PAGE_NEWS=1, - PAGE_GAME, - PAGE_SERVER_INFO, - PAGE_CALLVOTE, - PAGE_INTERNET, - PAGE_LAN, - PAGE_FAVORITES, - PAGE_DEMOS, - PAGE_SETTINGS, - PAGE_SYSTEM, - }; - - int game_page; - int popup; - int active_page; - bool menu_active; - vec2 mouse_pos; - - int64 last_input; - - // - char message_topic[512]; - char message_body[512]; - char message_button[512]; - - void popup_message(const char *topic, const char *body, const char *button); - - // TODO: this is a bit ugly but.. well.. yeah - enum { MAX_INPUTEVENTS = 32 }; - static INPUT_EVENT inputevents[MAX_INPUTEVENTS]; - static int num_inputevents; - - // some settings - static float button_height; - static float listheader_height; - static float fontmod_height; - - // for graphic settings - bool need_restart; - bool need_sendinfo; - - // - bool escape_pressed; - bool enter_pressed; - - // for call vote - int callvote_selectedoption; - int callvote_selectedplayer; - - // demo - struct DEMOITEM - { - char filename[512]; - char name[256]; - - bool operator<(const DEMOITEM &other) { return str_comp(name, other.name) < 0; } - }; - - sorted_array<DEMOITEM> demos; - - void demolist_populate(); - static void demolist_count_callback(const char *name, int is_dir, void *user); - static void demolist_fetch_callback(const char *name, int is_dir, void *user); - - // found in menus.cpp - int render(); - //void render_background(); - //void render_loading(float percent); - int render_menubar(CUIRect r); - void render_news(CUIRect main_view); - - // found in menus_demo.cpp - void render_demoplayer(CUIRect main_view); - void render_demolist(CUIRect main_view); - - // found in menus_ingame.cpp - void render_game(CUIRect main_view); - void render_serverinfo(CUIRect main_view); - void render_servercontrol(CUIRect main_view); - void render_servercontrol_kick(CUIRect main_view); - void render_servercontrol_server(CUIRect main_view); - - // found in menus_browser.cpp - int selected_index; - void render_serverbrowser_serverlist(CUIRect view); - void render_serverbrowser_serverdetail(CUIRect view); - void render_serverbrowser_filters(CUIRect view); - void render_serverbrowser(CUIRect main_view); - - // found in menus_settings.cpp - void render_settings_general(CUIRect main_view); - void render_settings_player(CUIRect main_view); - void render_settings_controls(CUIRect main_view); - void render_settings_graphics(CUIRect main_view); - void render_settings_sound(CUIRect main_view); - void render_settings(CUIRect main_view); - - void set_active(bool active); -public: - void render_background(); - - - static MENUS_KEYBINDER binder; - - MENUS(); - - void render_loading(float percent); - - bool is_active() const { return menu_active; } - - virtual void on_init(); - - virtual void on_statechange(int new_state, int old_state); - virtual void on_reset(); - virtual void on_render(); - virtual bool on_input(INPUT_EVENT e); - virtual bool on_mousemove(float x, float y); -}; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index dcf68f8d..0a737052 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1,46 +1,45 @@ +#include <engine/serverbrowser.h> +#include <engine/textrender.h> +#include <engine/keys.h> +#include <engine/shared/config.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> + +#include <game/client/ui.h> +#include <game/client/render.h> +#include "menus.h" +#include <game/localization.h> +#include <game/version.h> + +void CMenus::RenderServerbrowserServerList(CUIRect View) +{ + CUIRect Headers; + CUIRect Status; -#include <string.h> // strcmp, strlen, strncpy -#include <stdlib.h> // atoi - -#include <engine/e_client_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> - -#include <game/client/ui.hpp> -#include <game/client/render.hpp> -#include "menus.hpp" -#include <game/localization.hpp> -#include <game/version.hpp> + View.HSplitTop(ms_ListheaderHeight, &Headers, &View); + View.HSplitBottom(28.0f, &View, &Status); -void MENUS::render_serverbrowser_serverlist(CUIRect view) -{ - CUIRect headers; - CUIRect status; - - view.HSplitTop(listheader_height, &headers, &view); - view.HSplitBottom(28.0f, &view, &status); - // split of the scrollbar - RenderTools()->DrawUIRect(&headers, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - headers.VSplitRight(20.0f, &headers, 0); - - struct column + RenderTools()->DrawUIRect(&Headers, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); + Headers.VSplitRight(20.0f, &Headers, 0); + + struct CColumn { - int id; - int sort; - LOC_CONSTSTRING caption; - int direction; - float width; - int flags; - CUIRect rect; - CUIRect spacer; + int m_Id; + int m_Sort; + CLocConstString m_Caption; + int m_Direction; + float m_Width; + int m_Flags; + CUIRect m_Rect; + CUIRect m_Spacer; }; - + enum { FIXED=1, SPACER=2, - + COL_FLAG_LOCK=0, COL_FLAG_PURE, COL_FLAG_FAV, @@ -51,494 +50,542 @@ void MENUS::render_serverbrowser_serverlist(CUIRect view) COL_PING, COL_VERSION, }; - - static column cols[] = { + + static CColumn s_aCols[] = { {-1, -1, " ", -1, 2.0f, 0, {0}, {0}}, {COL_FLAG_LOCK, -1, " ", -1, 14.0f, 0, {0}, {0}}, {COL_FLAG_PURE, -1, " ", -1, 14.0f, 0, {0}, {0}}, {COL_FLAG_FAV, -1, " ", -1, 14.0f, 0, {0}, {0}}, - {COL_NAME, BROWSESORT_NAME, localize("Name"), 0, 300.0f, 0, {0}, {0}}, - {COL_GAMETYPE, BROWSESORT_GAMETYPE, localize("Type"), 1, 50.0f, 0, {0}, {0}}, - {COL_MAP, BROWSESORT_MAP, localize("Map"), 1, 100.0f, 0, {0}, {0}}, - {COL_PLAYERS, BROWSESORT_NUMPLAYERS, localize("Players"), 1, 60.0f, 0, {0}, {0}}, + {COL_NAME, IServerBrowser::SORT_NAME, Localize("Name"), 0, 300.0f, 0, {0}, {0}}, + {COL_GAMETYPE, IServerBrowser::SORT_GAMETYPE, Localize("Type"), 1, 50.0f, 0, {0}, {0}}, + {COL_MAP, IServerBrowser::SORT_MAP, Localize("Map"), 1, 100.0f, 0, {0}, {0}}, + {COL_PLAYERS, IServerBrowser::SORT_NUMPLAYERS, Localize("Players"), 1, 60.0f, 0, {0}, {0}}, {-1, -1, " ", 1, 10.0f, 0, {0}, {0}}, - {COL_PING, BROWSESORT_PING, localize("Ping"), 1, 40.0f, FIXED, {0}, {0}}, + {COL_PING, IServerBrowser::SORT_PING, Localize("Ping"), 1, 40.0f, FIXED, {0}, {0}}, }; - - int num_cols = sizeof(cols)/sizeof(column); - + + int NumCols = sizeof(s_aCols)/sizeof(CColumn); + // do layout - for(int i = 0; i < num_cols; i++) + for(int i = 0; i < NumCols; i++) { - if(cols[i].direction == -1) + if(s_aCols[i].m_Direction == -1) { - headers.VSplitLeft(cols[i].width, &cols[i].rect, &headers); - - if(i+1 < num_cols) + Headers.VSplitLeft(s_aCols[i].m_Width, &s_aCols[i].m_Rect, &Headers); + + if(i+1 < NumCols) { - //cols[i].flags |= SPACER; - headers.VSplitLeft(2, &cols[i].spacer, &headers); + //Cols[i].flags |= SPACER; + Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers); } } } - - for(int i = num_cols-1; i >= 0; i--) + + for(int i = NumCols-1; i >= 0; i--) { - if(cols[i].direction == 1) + if(s_aCols[i].m_Direction == 1) { - headers.VSplitRight(cols[i].width, &headers, &cols[i].rect); - headers.VSplitRight(2, &headers, &cols[i].spacer); + Headers.VSplitRight(s_aCols[i].m_Width, &Headers, &s_aCols[i].m_Rect); + Headers.VSplitRight(2, &Headers, &s_aCols[i].m_Spacer); } } - - for(int i = 0; i < num_cols; i++) + + for(int i = 0; i < NumCols; i++) { - if(cols[i].direction == 0) - cols[i].rect = headers; + if(s_aCols[i].m_Direction == 0) + s_aCols[i].m_Rect = Headers; } - + // do headers - for(int i = 0; i < num_cols; i++) + for(int i = 0; i < NumCols; i++) { - if(DoButton_GridHeader(cols[i].caption, cols[i].caption, config.b_sort == cols[i].sort, &cols[i].rect)) + if(DoButton_GridHeader(s_aCols[i].m_Caption, s_aCols[i].m_Caption, g_Config.m_BrSort == s_aCols[i].m_Sort, &s_aCols[i].m_Rect)) { - if(cols[i].sort != -1) + if(s_aCols[i].m_Sort != -1) { - if(config.b_sort == cols[i].sort) - config.b_sort_order ^= 1; + if(g_Config.m_BrSort == s_aCols[i].m_Sort) + g_Config.m_BrSortOrder ^= 1; else - config.b_sort_order = 0; - config.b_sort = cols[i].sort; + g_Config.m_BrSortOrder = 0; + g_Config.m_BrSort = s_aCols[i].m_Sort; } } } - - RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.15f), 0, 0); - - CUIRect scroll; - view.VSplitRight(15, &view, &scroll); - - int num_servers = client_serverbrowse_sorted_num(); - + + RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0); + + CUIRect Scroll; + View.VSplitRight(15, &View, &Scroll); + + int NumServers = ServerBrowser()->NumSortedServers(); + // display important messages in the middle of the screen so no // users misses it { - CUIRect msgbox = view; - msgbox.y += view.h/3; - - if(active_page == PAGE_INTERNET && client_serverbrowse_refreshingmasters()) - UI()->DoLabel(&msgbox, localize("Refreshing master servers"), 16.0f, 0); - else if(!client_serverbrowse_num()) - UI()->DoLabel(&msgbox, localize("No servers found"), 16.0f, 0); - else if(client_serverbrowse_num() && !num_servers) - UI()->DoLabel(&msgbox, localize("No servers match your filter criteria"), 16.0f, 0); + CUIRect MsgBox = View; + MsgBox.y += View.h/3; + + if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters()) + UI()->DoLabel(&MsgBox, Localize("Refreshing master servers"), 16.0f, 0); + else if(!ServerBrowser()->NumServers()) + UI()->DoLabel(&MsgBox, Localize("No servers found"), 16.0f, 0); + else if(ServerBrowser()->NumServers() && !NumServers) + UI()->DoLabel(&MsgBox, Localize("No servers match your filter criteria"), 16.0f, 0); } - int num = (int)(view.h/cols[0].rect.h); - static int scrollbar = 0; - static float scrollvalue = 0; - //static int selected_index = -1; - scroll.HMargin(5.0f, &scroll); - scrollvalue = DoScrollbarV(&scrollbar, &scroll, scrollvalue); - - int scrollnum = num_servers-num+10; - if(scrollnum > 0) + int Num = (int)(View.h/s_aCols[0].m_Rect.h); + static int s_ScrollBar = 0; + static float s_ScrollValue = 0; + + Scroll.HMargin(5.0f, &Scroll); + s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue); + + int ScrollNum = NumServers-Num+10; + if(ScrollNum > 0) { - if(inp_key_presses(KEY_MOUSE_WHEEL_UP)) - scrollvalue -= 1.0f/scrollnum; - if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN)) - scrollvalue += 1.0f/scrollnum; - - if(scrollvalue < 0) scrollvalue = 0; - if(scrollvalue > 1) scrollvalue = 1; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + s_ScrollValue -= 1.0f/ScrollNum; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + s_ScrollValue += 1.0f/ScrollNum; } else - scrollnum = 0; + ScrollNum = 0; + + if(m_SelectedIndex > -1) + { + for(int i = 0; i < m_NumInputEvents; i++) + { + int NewIndex = -1; + if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS) + { + if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = m_SelectedIndex + 1; + if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = m_SelectedIndex - 1; + } + if(NewIndex > -1 && NewIndex < NumServers) + { + //scroll + if(ScrollNum) + { + if(NewIndex - m_SelectedIndex > 0) + s_ScrollValue += 1.0f/ScrollNum; + else + s_ScrollValue -= 1.0f/ScrollNum; + } + + m_SelectedIndex = NewIndex; + + const CServerInfo *pItem = ServerBrowser()->SortedGet(m_SelectedIndex); + str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); + } + } + } + + if(s_ScrollValue < 0) s_ScrollValue = 0; + if(s_ScrollValue > 1) s_ScrollValue = 1; // set clipping - UI()->ClipEnable(&view); - - int start = (int)(scrollnum*scrollvalue); - if(start < 0) - start = 0; - - CUIRect original_view = view; - view.y -= scrollvalue*scrollnum*cols[0].rect.h; - - int new_selected = -1; - int num_players = 0; + UI()->ClipEnable(&View); + + CUIRect OriginalView = View; + View.y -= s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h; - selected_index = -1; + int NewSelected = -1; + int NumPlayers = 0; - for (int i = 0; i < num_servers; i++) + m_SelectedIndex = -1; + + for (int i = 0; i < NumServers; i++) { - SERVER_INFO *item = client_serverbrowse_sorted_get(i); - num_players += item->num_players; + const CServerInfo *pItem = ServerBrowser()->SortedGet(i); + NumPlayers += pItem->m_NumPlayers; } - - for (int i = 0; i < num_servers; i++) + + for (int i = 0; i < NumServers; i++) { - int item_index = i; - SERVER_INFO *item = client_serverbrowse_sorted_get(item_index); - CUIRect row; - CUIRect select_hit_box; - - int selected = strcmp(item->address, config.ui_server_address) == 0; //selected_index==item_index; - - view.HSplitTop(17.0f, &row, &view); - select_hit_box = row; - - if(selected) - { - selected_index = i; - CUIRect r = row; - r.Margin(1.5f, &r); - RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); - } + int ItemIndex = i; + const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex); + CUIRect Row; + CUIRect SelectHitBox; + + int Selected = str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0; //selected_index==ItemIndex; + View.HSplitTop(17.0f, &Row, &View); + SelectHitBox = Row; + + if(Selected) + m_SelectedIndex = i; // make sure that only those in view can be selected - if(row.y+row.h > original_view.y) + if(Row.y+Row.h > OriginalView.y && Row.y < OriginalView.y+OriginalView.h) { - if(select_hit_box.y < original_view.y) // clip the selection + if(Selected) + { + CUIRect r = Row; + r.Margin(1.5f, &r); + RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); + } + + // clip the selection + if(SelectHitBox.y < OriginalView.y) // top { - select_hit_box.h -= original_view.y-select_hit_box.y; - select_hit_box.y = original_view.y; + SelectHitBox.h -= OriginalView.y-SelectHitBox.y; + SelectHitBox.y = OriginalView.y; } - - if(UI()->DoButtonLogic(item, "", selected, &select_hit_box)) + else if(SelectHitBox.y+SelectHitBox.h > OriginalView.y+OriginalView.h) // bottom + SelectHitBox.h = OriginalView.y+OriginalView.h-SelectHitBox.y; + + if(UI()->DoButtonLogic(pItem, "", Selected, &SelectHitBox)) { - new_selected = item_index; + NewSelected = ItemIndex; } } - - // check if we need to do more - if(row.y > original_view.y+original_view.h) - break; + else + { + // reset active item, if not visible + if(UI()->ActiveItem() == pItem) + UI()->SetActiveItem(0); - for(int c = 0; c < num_cols; c++) + // don't render invisible items + continue; + } + + for(int c = 0; c < NumCols; c++) { - CUIRect button; - char temp[64]; - button.x = cols[c].rect.x; - button.y = row.y; - button.h = row.h; - button.w = cols[c].rect.w; - - //int s = 0; - int id = cols[c].id; - - //s = UI()->DoButton(item, "L", l, &button, ui_draw_browse_icon, 0); - - if(id == COL_FLAG_LOCK) + CUIRect Button; + char aTemp[64]; + Button.x = s_aCols[c].m_Rect.x; + Button.y = Row.y; + Button.h = Row.h; + Button.w = s_aCols[c].m_Rect.w; + + int Id = s_aCols[c].m_Id; + + if(Id == COL_FLAG_LOCK) { - if(item->flags & SRVFLAG_PASSWORD) - DoButton_BrowseIcon(SPRITE_BROWSE_LOCK, &button); + if(pItem->m_Flags & SERVER_FLAG_PASSWORD) + DoButton_BrowseIcon(SPRITE_BROWSE_LOCK, &Button); } - else if(id == COL_FLAG_PURE) + else if(Id == COL_FLAG_PURE) { - if(strcmp(item->gametype, "DM") == 0 || strcmp(item->gametype, "TDM") == 0 || strcmp(item->gametype, "CTF") == 0) + if( str_comp(pItem->m_aGameType, "DM") == 0 || + str_comp(pItem->m_aGameType, "TDM") == 0 || + str_comp(pItem->m_aGameType, "CTF") == 0) { // pure server } else { // unpure - DoButton_BrowseIcon(SPRITE_BROWSE_UNPURE, &button); + DoButton_BrowseIcon(SPRITE_BROWSE_UNPURE, &Button); } } - else if(id == COL_FLAG_FAV) + else if(Id == COL_FLAG_FAV) { - if(item->favorite) - DoButton_BrowseIcon(SPRITE_BROWSE_HEART, &button); + if(pItem->m_Favorite) + DoButton_BrowseIcon(SPRITE_BROWSE_HEART, &Button); } - else if(id == COL_NAME) + else if(Id == COL_NAME) { - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, button.x, button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - cursor.line_width = button.w; - - if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_SERVERNAME)) + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = Button.w; + + if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME)) { // highlight the parts that matches - const char *s = str_find_nocase(item->name, config.b_filter_string); + const char *s = str_find_nocase(pItem->m_aName, g_Config.m_BrFilterString); if(s) { - gfx_text_ex(&cursor, item->name, (int)(s-item->name)); - gfx_text_color(0.4f,0.4f,1.0f,1); - gfx_text_ex(&cursor, s, strlen(config.b_filter_string)); - gfx_text_color(1,1,1,1); - gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1); + TextRender()->TextEx(&Cursor, pItem->m_aName, (int)(s-pItem->m_aName)); + TextRender()->TextColor(0.4f,0.4f,1.0f,1); + TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextColor(1,1,1,1); + TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); } else - gfx_text_ex(&cursor, item->name, -1); + TextRender()->TextEx(&Cursor, pItem->m_aName, -1); } else - gfx_text_ex(&cursor, item->name, -1); + TextRender()->TextEx(&Cursor, pItem->m_aName, -1); } - else if(id == COL_MAP) - UI()->DoLabel(&button, item->map, 12.0f, -1); - else if(id == COL_PLAYERS) + else if(Id == COL_MAP) + UI()->DoLabel(&Button, pItem->m_aMap, 12.0f, -1); + else if(Id == COL_PLAYERS) { - str_format(temp, sizeof(temp), "%i/%i", item->num_players, item->max_players); - if(config.b_filter_string[0] && (item->quicksearch_hit&BROWSEQUICK_PLAYERNAME)) - gfx_text_color(0.4f,0.4f,1.0f,1); - UI()->DoLabel(&button, temp, 12.0f, 1); - gfx_text_color(1,1,1,1); + str_format(aTemp, sizeof(aTemp), "%i/%i", pItem->m_NumPlayers, pItem->m_MaxPlayers); + if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit&IServerBrowser::QUICK_PLAYERNAME)) + TextRender()->TextColor(0.4f,0.4f,1.0f,1); + UI()->DoLabel(&Button, aTemp, 12.0f, 1); + TextRender()->TextColor(1,1,1,1); } - else if(id == COL_PING) + else if(Id == COL_PING) { - str_format(temp, sizeof(temp), "%i", item->latency); - UI()->DoLabel(&button, temp, 12.0f, 1); + str_format(aTemp, sizeof(aTemp), "%i", pItem->m_Latency); + UI()->DoLabel(&Button, aTemp, 12.0f, 1); } - else if(id == COL_VERSION) + else if(Id == COL_VERSION) { - const char *version = item->version; - if(strcmp(version, "0.3 e2d7973c6647a13c") == 0) // TODO: remove me later on - version = "0.3.0"; - UI()->DoLabel(&button, version, 12.0f, 1); - } - else if(id == COL_GAMETYPE) + const char *pVersion = pItem->m_aVersion; + if(str_comp(pVersion, "0.3 e2d7973c6647a13c") == 0) // TODO: remove me later on + pVersion = "0.3.0"; + UI()->DoLabel(&Button, pVersion, 12.0f, 1); + } + else if(Id == COL_GAMETYPE) { - UI()->DoLabel(&button, item->gametype, 12.0f, 0); + UI()->DoLabel(&Button, pItem->m_aGameType, 12.0f, 0); } } } UI()->ClipDisable(); - - if(new_selected != -1) + + if(NewSelected != -1) { // select the new server - SERVER_INFO *item = client_serverbrowse_sorted_get(new_selected); - strncpy(config.ui_server_address, item->address, sizeof(config.ui_server_address)); - if(inp_mouse_doubleclick()) - client_connect(config.ui_server_address); + const CServerInfo *pItem = ServerBrowser()->SortedGet(NewSelected); + str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); + if(Input()->MouseDoubleClick()) + Client()->Connect(g_Config.m_UiServerAddress); } - RenderTools()->DrawUIRect(&status, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - status.Margin(5.0f, &status); - + RenderTools()->DrawUIRect(&Status, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); + Status.Margin(5.0f, &Status); + // render quick search - CUIRect quicksearch; - status.VSplitLeft(250.0f, &quicksearch, &status); - const char *label = localize("Quick search"); - UI()->DoLabel(&quicksearch, label, 14.0f, -1); - quicksearch.VSplitLeft(gfx_text_width(0, 14.0f, label, -1), 0, &quicksearch); - quicksearch.VSplitLeft(5, 0, &quicksearch); - DoEditBox(&config.b_filter_string, &quicksearch, config.b_filter_string, sizeof(config.b_filter_string), 14.0f); - + CUIRect QuickSearch, Button; + Status.VSplitLeft(260.0f, &QuickSearch, &Status); + const char *pLabel = Localize("Quick search:"); + UI()->DoLabel(&QuickSearch, pLabel, 12.0f, -1); + QuickSearch.VSplitLeft(TextRender()->TextWidth(0, 12.0f, pLabel, -1), 0, &QuickSearch); + QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch); + QuickSearch.VSplitLeft(155.0f, &QuickSearch, &Button); + DoEditBox(&g_Config.m_BrFilterString, &QuickSearch, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), 12.0f, false, CUI::CORNER_L); + // clear button + { + static int s_ClearButton = 0; + RenderTools()->DrawUIRect(&Button, vec4(1,1,1,0.33f)*ButtonColorMul(&s_ClearButton), CUI::CORNER_R, 3.0f); + UI()->DoLabel(&Button, "x", Button.h*ms_FontmodHeight, 0); + if(UI()->DoButtonLogic(&s_ClearButton, "x", 0, &Button)) + { + g_Config.m_BrFilterString[0] = 0; + UI()->SetActiveItem(&g_Config.m_BrFilterString); + } + } + // render status - char buf[128]; - str_format(buf, sizeof(buf), localize("%d of %d servers, %d players"), client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players); - status.VSplitRight(gfx_text_width(0, 14.0f, buf, -1), 0, &status); - UI()->DoLabel(&status, buf, 14.0f, -1); + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers, %d players"), ServerBrowser()->NumSortedServers(), ServerBrowser()->NumServers(), NumPlayers); + Status.VSplitRight(TextRender()->TextWidth(0, 14.0f, aBuf, -1), 0, &Status); + UI()->DoLabel(&Status, aBuf, 14.0f, -1); } -void MENUS::render_serverbrowser_filters(CUIRect view) +void CMenus::RenderServerbrowserFilters(CUIRect View) { // filters - CUIRect button; + CUIRect Button; - view.HSplitTop(5.0f, 0, &view); - view.VSplitLeft(5.0f, 0, &view); - view.VSplitRight(5.0f, &view, 0); - view.HSplitBottom(5.0f, &view, 0); + View.HSplitTop(5.0f, 0, &View); + View.VSplitLeft(5.0f, 0, &View); + View.VSplitRight(5.0f, &View, 0); + View.HSplitBottom(5.0f, &View, 0); // render filters - view.HSplitTop(20.0f, &button, &view); - if (DoButton_CheckBox(&config.b_filter_empty, localize("Has people playing"), config.b_filter_empty, &button)) - config.b_filter_empty ^= 1; + View.HSplitTop(20.0f, &Button, &View); + if (DoButton_CheckBox(&g_Config.m_BrFilterEmpty, Localize("Has people playing"), g_Config.m_BrFilterEmpty, &Button)) + g_Config.m_BrFilterEmpty ^= 1; - view.HSplitTop(20.0f, &button, &view); - if (DoButton_CheckBox(&config.b_filter_full, localize("Server not full"), config.b_filter_full, &button)) - config.b_filter_full ^= 1; + View.HSplitTop(20.0f, &Button, &View); + if (DoButton_CheckBox(&g_Config.m_BrFilterFull, Localize("Server not full"), g_Config.m_BrFilterFull, &Button)) + g_Config.m_BrFilterFull ^= 1; - view.HSplitTop(20.0f, &button, &view); - if (DoButton_CheckBox(&config.b_filter_pw, localize("No password"), config.b_filter_pw, &button)) - config.b_filter_pw ^= 1; + View.HSplitTop(20.0f, &Button, &View); + if (DoButton_CheckBox(&g_Config.m_BrFilterPw, Localize("No password"), g_Config.m_BrFilterPw, &Button)) + g_Config.m_BrFilterPw ^= 1; - view.HSplitTop(20.0f, &button, &view); - if (DoButton_CheckBox((char *)&config.b_filter_compatversion, localize("Compatible version"), config.b_filter_compatversion, &button)) - config.b_filter_compatversion ^= 1; + View.HSplitTop(20.0f, &Button, &View); + if (DoButton_CheckBox((char *)&g_Config.m_BrFilterCompatversion, Localize("Compatible version"), g_Config.m_BrFilterCompatversion, &Button)) + g_Config.m_BrFilterCompatversion ^= 1; + + View.HSplitTop(20.0f, &Button, &View); + if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPure, Localize("Standard gametype"), g_Config.m_BrFilterPure, &Button)) + g_Config.m_BrFilterPure ^= 1; + + View.HSplitTop(20.0f, &Button, &View); + //button.VSplitLeft(20.0f, 0, &button); + if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button)) + g_Config.m_BrFilterPureMap ^= 1; - view.HSplitTop(20.0f, &button, &view); - if (DoButton_CheckBox((char *)&config.b_filter_pure, localize("Standard gametype"), config.b_filter_pure, &button)) - config.b_filter_pure ^= 1; - - view.HSplitTop(20.0f, &button, &view); - /*button.VSplitLeft(20.0f, 0, &button);*/ - if (DoButton_CheckBox((char *)&config.b_filter_pure_map, localize("Standard map"), config.b_filter_pure_map, &button)) - config.b_filter_pure_map ^= 1; - - view.HSplitTop(20.0f, &button, &view); - UI()->DoLabel(&button, localize("Game types"), 14.0f, -1); - button.VSplitLeft(95.0f, 0, &button); - button.Margin(1.0f, &button); - DoEditBox(&config.b_filter_gametype, &button, config.b_filter_gametype, sizeof(config.b_filter_gametype), 14.0f); + View.HSplitTop(5.0f, 0, &View); + + View.HSplitTop(19.0f, &Button, &View); + UI()->DoLabel(&Button, Localize("Game types:"), 12.0f, -1); + Button.VSplitLeft(95.0f, 0, &Button); + View.HSplitTop(3.0f, 0, &View); + DoEditBox(&g_Config.m_BrFilterGametype, &Button, g_Config.m_BrFilterGametype, sizeof(g_Config.m_BrFilterGametype), 12.0f); { - view.HSplitTop(20.0f, &button, &view); - CUIRect editbox; - button.VSplitLeft(40.0f, &editbox, &button); - button.VSplitLeft(5.0f, &button, &button); + View.HSplitTop(19.0f, &Button, &View); + CUIRect EditBox; + Button.VSplitRight(50.0f, &Button, &EditBox); + EditBox.VSplitRight(5.0f, &EditBox, 0); - char buf[8]; - str_format(buf, sizeof(buf), "%d", config.b_filter_ping); - DoEditBox(&config.b_filter_ping, &editbox, buf, sizeof(buf), 14.0f); - config.b_filter_ping = atoi(buf); + UI()->DoLabel(&Button, Localize("Maximum ping:"), 12.0f, -1); - UI()->DoLabel(&button, localize("Maximum ping"), 14.0f, -1); + char aBuf[5]; + str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing); + DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), 12.0f); + g_Config.m_BrFilterPing = str_toint(aBuf); } - - view.HSplitBottom(button_height, &view, &button); - static int clear_button = 0; - if(DoButton_Menu(&clear_button, localize("Reset filter"), 0, &button)) + + View.HSplitBottom(ms_ButtonHeight, &View, &Button); + static int s_ClearButton = 0; + if(DoButton_Menu(&s_ClearButton, Localize("Reset filter"), 0, &Button)) { - config.b_filter_full = 0; - config.b_filter_empty = 0; - config.b_filter_pw = 0; - config.b_filter_ping = 999; - config.b_filter_gametype[0] = 0; - config.b_filter_compatversion = 1; - config.b_filter_string[0] = 0; - config.b_filter_pure = 1; + g_Config.m_BrFilterFull = 0; + g_Config.m_BrFilterEmpty = 0; + g_Config.m_BrFilterPw = 0; + g_Config.m_BrFilterPing = 999; + g_Config.m_BrFilterGametype[0] = 0; + g_Config.m_BrFilterCompatversion = 1; + g_Config.m_BrFilterString[0] = 0; + g_Config.m_BrFilterPure = 1; + g_Config.m_BrFilterPureMap = 1; } } -void MENUS::render_serverbrowser_serverdetail(CUIRect view) +void CMenus::RenderServerbrowserServerDetail(CUIRect View) { - CUIRect server_details = view; - CUIRect server_scoreboard, server_header; - - SERVER_INFO *selected_server = client_serverbrowse_sorted_get(selected_index); - + CUIRect ServerDetails = View; + CUIRect ServerScoreBoard, ServerHeader; + + const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex); + //server_details.VSplitLeft(10.0f, 0x0, &server_details); // split off a piece to use for scoreboard - server_details.HSplitTop(140.0f, &server_details, &server_scoreboard); - server_details.HSplitBottom(10.0f, &server_details, 0x0); + ServerDetails.HSplitTop(140.0f, &ServerDetails, &ServerScoreBoard); + ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0); // server details - const float font_size = 12.0f; - server_details.HSplitTop(20.0f, &server_header, &server_details); - RenderTools()->DrawUIRect(&server_header, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); - RenderTools()->DrawUIRect(&server_details, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); - server_header.VSplitLeft(8.0f, 0x0, &server_header); - UI()->DoLabel(&server_header, localize("Server details"), font_size+2.0f, -1); + const float FontSize = 12.0f; + ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails); + RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); + RenderTools()->DrawUIRect(&ServerDetails, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); + ServerHeader.VSplitLeft(8.0f, 0x0, &ServerHeader); + UI()->DoLabel(&ServerHeader, Localize("Server details"), FontSize+2.0f, -1); - server_details.VSplitLeft(5.0f, 0x0, &server_details); + ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails); - server_details.Margin(3.0f, &server_details); + ServerDetails.Margin(3.0f, &ServerDetails); - if (selected_server) + if (pSelectedServer) { - CUIRect row; - static LOC_CONSTSTRING labels[] = { - localize("Version"), - localize("Game type"), - localize("Ping")}; + CUIRect Row; + static CLocConstString s_aLabels[] = { + Localize("Version"), + Localize("Game type"), + Localize("Ping")}; - CUIRect left_column; - CUIRect right_column; + CUIRect LeftColumn; + CUIRect RightColumn; - // + // { - CUIRect button; - server_details.HSplitBottom(20.0f, &server_details, &button); - static int add_fav_button = 0; - if(DoButton_CheckBox(&add_fav_button, localize("Favorite"), selected_server->favorite, &button)) + CUIRect Button; + ServerDetails.HSplitBottom(20.0f, &ServerDetails, &Button); + static int s_AddFavButton = 0; + if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &Button)) { - if(selected_server->favorite) - client_serverbrowse_removefavorite(selected_server->netaddr); + if(pSelectedServer->m_Favorite) + ServerBrowser()->RemoveFavorite(pSelectedServer->m_NetAddr); else - client_serverbrowse_addfavorite(selected_server->netaddr); + ServerBrowser()->AddFavorite(pSelectedServer->m_NetAddr); } } - //UI()->DoLabel(&row, temp, font_size, -1); + //UI()->DoLabel(&row, temp, font_size, -1); - server_details.VSplitLeft(5.0f, 0x0, &server_details); - server_details.VSplitLeft(80.0f, &left_column, &right_column); + ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails); + ServerDetails.VSplitLeft(80.0f, &LeftColumn, &RightColumn); - for (unsigned int i = 0; i < sizeof(labels) / sizeof(labels[0]); i++) + for (unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++) { - left_column.HSplitTop(15.0f, &row, &left_column); - UI()->DoLabel(&row, labels[i], font_size, -1); + LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn); + UI()->DoLabel(&Row, s_aLabels[i], FontSize, -1); } - right_column.HSplitTop(15.0f, &row, &right_column); - UI()->DoLabel(&row, selected_server->version, font_size, -1); + RightColumn.HSplitTop(15.0f, &Row, &RightColumn); + UI()->DoLabel(&Row, pSelectedServer->m_aVersion, FontSize, -1); - right_column.HSplitTop(15.0f, &row, &right_column); - UI()->DoLabel(&row, selected_server->gametype, font_size, -1); + RightColumn.HSplitTop(15.0f, &Row, &RightColumn); + UI()->DoLabel(&Row, pSelectedServer->m_aGameType, FontSize, -1); - char temp[16]; - str_format(temp, sizeof(temp), "%d", selected_server->latency); - right_column.HSplitTop(15.0f, &row, &right_column); - UI()->DoLabel(&row, temp, font_size, -1); + char aTemp[16]; + str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency); + RightColumn.HSplitTop(15.0f, &Row, &RightColumn); + UI()->DoLabel(&Row, aTemp, FontSize, -1); } - + // server scoreboard - - server_scoreboard.HSplitBottom(10.0f, &server_scoreboard, 0x0); - server_scoreboard.HSplitTop(20.0f, &server_header, &server_scoreboard); - RenderTools()->DrawUIRect(&server_header, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); - RenderTools()->DrawUIRect(&server_scoreboard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); - server_header.VSplitLeft(8.0f, 0x0, &server_header); - UI()->DoLabel(&server_header, localize("Scoreboard"), font_size+2.0f, -1); - server_scoreboard.VSplitLeft(5.0f, 0x0, &server_scoreboard); + ServerScoreBoard.HSplitBottom(10.0f, &ServerScoreBoard, 0x0); + ServerScoreBoard.HSplitTop(20.0f, &ServerHeader, &ServerScoreBoard); + RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); + RenderTools()->DrawUIRect(&ServerScoreBoard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); + ServerHeader.VSplitLeft(8.0f, 0x0, &ServerHeader); + UI()->DoLabel(&ServerHeader, Localize("Scoreboard"), FontSize+2.0f, -1); - server_scoreboard.Margin(3.0f, &server_scoreboard); + ServerScoreBoard.VSplitLeft(5.0f, 0x0, &ServerScoreBoard); - if (selected_server) + ServerScoreBoard.Margin(3.0f, &ServerScoreBoard); + + if (pSelectedServer) { - for (int i = 0; i < selected_server->num_players; i++) + for (int i = 0; i < pSelectedServer->m_NumPlayers; i++) { - CUIRect row; - char temp[16]; - server_scoreboard.HSplitTop(16.0f, &row, &server_scoreboard); + CUIRect Row; + char aTemp[16]; + ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard); - str_format(temp, sizeof(temp), "%d", selected_server->players[i].score); - UI()->DoLabel(&row, temp, font_size, -1); + str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score); + UI()->DoLabel(&Row, aTemp, FontSize, -1); - row.VSplitLeft(25.0f, 0x0, &row); - - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, row.x, row.y, 12.0f, TEXTFLAG_RENDER); - - const char *name = selected_server->players[i].name; - if(config.b_filter_string[0]) + Row.VSplitLeft(25.0f, 0x0, &Row); + + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Row.x, Row.y, 12.0f, TEXTFLAG_RENDER); + + const char *pName = pSelectedServer->m_aPlayers[i].m_aName; + if(g_Config.m_BrFilterString[0]) { // highlight the parts that matches - const char *s = str_find_nocase(name, config.b_filter_string); + const char *s = str_find_nocase(pName, g_Config.m_BrFilterString); if(s) { - gfx_text_ex(&cursor, name, (int)(s-name)); - gfx_text_color(0.4f,0.4f,1,1); - gfx_text_ex(&cursor, s, strlen(config.b_filter_string)); - gfx_text_color(1,1,1,1); - gfx_text_ex(&cursor, s+strlen(config.b_filter_string), -1); + TextRender()->TextEx(&Cursor, pName, (int)(s-pName)); + TextRender()->TextColor(0.4f,0.4f,1,1); + TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString)); + TextRender()->TextColor(1,1,1,1); + TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1); } else - gfx_text_ex(&cursor, name, -1); + TextRender()->TextEx(&Cursor, pName, -1); } else - gfx_text_ex(&cursor, name, -1); - + TextRender()->TextEx(&Cursor, pName, -1); + } } } -void MENUS::render_serverbrowser(CUIRect main_view) +void CMenus::RenderServerbrowser(CUIRect MainView) { - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f); - - CUIRect view; - main_view.Margin(10.0f, &view); - + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); + + CUIRect View; + MainView.Margin(10.0f, &View); + /* +-----------------+ +------+ | | | | @@ -549,100 +596,103 @@ void MENUS::render_serverbrowser(CUIRect main_view) +-----------------+ button status toolbar box */ - - + + //CUIRect filters; - CUIRect status_toolbar; - CUIRect toolbox; - CUIRect button_box; + CUIRect StatusToolBox; + CUIRect ToolBox; + CUIRect ButtonBox; // split off a piece for filters, details and scoreboard - view.VSplitRight(200.0f, &view, &toolbox); - toolbox.HSplitBottom(80.0f, &toolbox, &button_box); - view.HSplitBottom(button_height+5.0f, &view, &status_toolbar); + View.VSplitRight(200.0f, &View, &ToolBox); + ToolBox.HSplitBottom(80.0f, &ToolBox, &ButtonBox); + View.HSplitBottom(ms_ButtonHeight+5.0f, &View, &StatusToolBox); - render_serverbrowser_serverlist(view); - - static int toolbox_page = 0; - - toolbox.VSplitLeft(5.0f, 0, &toolbox); + RenderServerbrowserServerList(View); + + int ToolboxPage = g_Config.m_UiToolboxPage; + + ToolBox.VSplitLeft(5.0f, 0, &ToolBox); // do tabbar { - CUIRect tab_bar; - CUIRect tabbutton0, tabbutton1; - toolbox.HSplitTop(22.0f, &tab_bar, &toolbox); - - tab_bar.VSplitMid(&tabbutton0, &tabbutton1); - tabbutton0.VSplitRight(5.0f, &tabbutton0, 0); - tabbutton1.VSplitLeft(5.0f, 0, &tabbutton1); - - static int filters_tab = 0; - if (DoButton_MenuTab(&filters_tab, localize("Filter"), toolbox_page==0, &tabbutton0, 0)) - toolbox_page = 0; - - static int info_tab = 0; - if (DoButton_MenuTab(&info_tab, localize("Info"), toolbox_page==1, &tabbutton1, 0)) - toolbox_page = 1; + CUIRect TabBar; + CUIRect TabButton0, TabButton1; + ToolBox.HSplitTop(22.0f, &TabBar, &ToolBox); + + TabBar.VSplitMid(&TabButton0, &TabButton1); + //TabButton0.VSplitRight(5.0f, &TabButton0, 0); + //TabButton1.VSplitLeft(5.0f, 0, &TabButton1); + + static int s_FiltersTab = 0; + if (DoButton_MenuTab(&s_FiltersTab, Localize("Filter"), ToolboxPage==0, &TabButton0, CUI::CORNER_TL)) + ToolboxPage = 0; + + static int s_InfoTab = 0; + if (DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage==1, &TabButton1, CUI::CORNER_TR)) + ToolboxPage = 1; } - RenderTools()->DrawUIRect(&toolbox, vec4(0,0,0,0.15f), 0, 0); - - toolbox.HSplitTop(5.0f, 0, &toolbox); - - if(toolbox_page == 0) - render_serverbrowser_filters(toolbox); - else if(toolbox_page == 1) - render_serverbrowser_serverdetail(toolbox); + g_Config.m_UiToolboxPage = ToolboxPage; + + RenderTools()->DrawUIRect(&ToolBox, vec4(0,0,0,0.15f), 0, 0); + + ToolBox.HSplitTop(5.0f, 0, &ToolBox); + + if(ToolboxPage == 0) + RenderServerbrowserFilters(ToolBox); + else if(ToolboxPage == 1) + RenderServerbrowserServerDetail(ToolBox); { - status_toolbar.HSplitTop(5.0f, 0, &status_toolbar); - - CUIRect button; + StatusToolBox.HSplitTop(5.0f, 0, &StatusToolBox); + + CUIRect Button; //buttons.VSplitRight(20.0f, &buttons, &button); - status_toolbar.VSplitRight(110.0f, &status_toolbar, &button); - button.VMargin(2.0f, &button); - static int refresh_button = 0; - if(DoButton_Menu(&refresh_button, localize("Refresh"), 0, &button)) + StatusToolBox.VSplitRight(110.0f, &StatusToolBox, &Button); + Button.VMargin(2.0f, &Button); + static int s_RefreshButton = 0; + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button)) { - if(config.ui_page == PAGE_INTERNET) - client_serverbrowse_refresh(BROWSETYPE_INTERNET); - else if(config.ui_page == PAGE_LAN) - client_serverbrowse_refresh(BROWSETYPE_LAN); - else if(config.ui_page == PAGE_FAVORITES) - client_serverbrowse_refresh(BROWSETYPE_FAVORITES); + if(g_Config.m_UiPage == PAGE_INTERNET) + ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); + else if(g_Config.m_UiPage == PAGE_LAN) + ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN); + else if(g_Config.m_UiPage == PAGE_FAVORITES) + ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); } - - char buf[512]; - if(strcmp(client_latestversion(), "0") != 0) - str_format(buf, sizeof(buf), localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), client_latestversion()); + + char aBuf[512]; + if(str_comp(Client()->LatestVersion(), "0") != 0) + str_format(aBuf, sizeof(aBuf), Localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), Client()->LatestVersion()); else - str_format(buf, sizeof(buf), localize("Current version: %s"), GAME_VERSION); - UI()->DoLabel(&status_toolbar, buf, 14.0f, -1); + str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION); + UI()->DoLabel(&StatusToolBox, aBuf, 14.0f, -1); } - + // do the button box { - - button_box.VSplitLeft(5.0f, 0, &button_box); - button_box.VSplitRight(5.0f, &button_box, 0); - - CUIRect button; - button_box.HSplitBottom(button_height, &button_box, &button); - button.VSplitRight(120.0f, 0, &button); - button.VMargin(2.0f, &button); + + ButtonBox.VSplitLeft(5.0f, 0, &ButtonBox); + ButtonBox.VSplitRight(5.0f, &ButtonBox, 0); + + CUIRect Button; + ButtonBox.HSplitBottom(ms_ButtonHeight, &ButtonBox, &Button); + Button.VSplitRight(120.0f, 0, &Button); + Button.VMargin(2.0f, &Button); //button.VMargin(2.0f, &button); - static int join_button = 0; - if(DoButton_Menu(&join_button, localize("Connect"), 0, &button) || enter_pressed) + static int s_JoinButton = 0; + if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &Button) || m_EnterPressed) { - client_connect(config.ui_server_address); - enter_pressed = false; + dbg_msg("", "%s", g_Config.m_UiServerAddress); + Client()->Connect(g_Config.m_UiServerAddress); + m_EnterPressed = false; } - - button_box.HSplitBottom(5.0f, &button_box, &button); - button_box.HSplitBottom(20.0f, &button_box, &button); - DoEditBox(&config.ui_server_address, &button, config.ui_server_address, sizeof(config.ui_server_address), 14.0f); - button_box.HSplitBottom(20.0f, &button_box, &button); - UI()->DoLabel(&button, localize("Host address"), 14.0f, -1); + + ButtonBox.HSplitBottom(5.0f, &ButtonBox, &Button); + ButtonBox.HSplitBottom(20.0f, &ButtonBox, &Button); + DoEditBox(&g_Config.m_UiServerAddress, &Button, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), 14.0f); + ButtonBox.HSplitBottom(20.0f, &ButtonBox, &Button); + UI()->DoLabel(&Button, Localize("Host address"), 14.0f, -1); } } diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 07019d46..62c03a92 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -1,86 +1,82 @@ -#include <base/math.hpp> +#include <base/math.h> -//#include <string.h> // strcmp, strlen, strncpy -//#include <stdlib.h> // atoi -#include <engine/e_client_interface.h> -#include <game/client/render.hpp> -#include <game/client/gameclient.hpp> +#include <engine/demo.h> +#include <engine/keys.h> -//#include <game/generated/g_protocol.hpp> -//#include <game/generated/gc_data.hpp> +#include <game/client/render.h> +#include <game/client/gameclient.h> +#include <game/localization.h> -#include <game/client/ui.hpp> -//#include <game/client/gameclient.hpp> -//#include <game/client/animstate.hpp> +#include <game/client/ui.h> -#include "menus.hpp" +#include "menus.h" -int MENUS::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect) +int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f); UI()->DoLabel(pRect, pText, 14.0f, 0); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -void MENUS::render_demoplayer(CUIRect main_view) +void CMenus::RenderDemoPlayer(CUIRect MainView) { - const DEMOPLAYBACK_INFO *info = client_demoplayer_getinfo(); + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - const float seekbar_height = 15.0f; - const float buttonbar_height = 20.0f; - const float margins = 5.0f; - float total_height; + const float SeekBarHeight = 15.0f; + const float ButtonbarHeight = 20.0f; + const float Margins = 5.0f; + float TotalHeight; - if(menu_active) - total_height = seekbar_height+buttonbar_height+margins*3; + if(m_MenuActive) + TotalHeight = SeekBarHeight+ButtonbarHeight+Margins*3; else - total_height = seekbar_height+margins*2; + TotalHeight = SeekBarHeight+Margins*2; - main_view.HSplitBottom(total_height, 0, &main_view); - main_view.VSplitLeft(250.0f, 0, &main_view); - main_view.VSplitRight(250.0f, &main_view, 0); + MainView.HSplitBottom(TotalHeight, 0, &MainView); + MainView.VSplitLeft(250.0f, 0, &MainView); + MainView.VSplitRight(250.0f, &MainView, 0); - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_T, 10.0f); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f); - main_view.Margin(5.0f, &main_view); + MainView.Margin(5.0f, &MainView); - CUIRect seekbar, buttonbar; + CUIRect SeekBar, ButtonBar; - if(menu_active) + if(m_MenuActive) { - main_view.HSplitTop(seekbar_height, &seekbar, &buttonbar); - buttonbar.HSplitTop(margins, 0, &buttonbar); + MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar); + ButtonBar.HSplitTop(Margins, 0, &ButtonBar); } else - seekbar = main_view; + SeekBar = MainView; // do seekbar { - static int seekbar_id = 0; - void *id = &seekbar_id; - char buffer[128]; + static int s_SeekBarId = 0; + void *id = &s_SeekBarId; + char aBuffer[128]; - RenderTools()->DrawUIRect(&seekbar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f); - int current_tick = info->current_tick - info->first_tick; - int total_ticks = info->last_tick - info->first_tick; + int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick; + int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick; - float amount = current_tick/(float)total_ticks; + float Amount = CurrentTick/(float)TotalTicks; - CUIRect filledbar = seekbar; - filledbar.w = 10.0f + (filledbar.w-10.0f)*amount; + CUIRect FilledBar = SeekBar; + FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount; - RenderTools()->DrawUIRect(&filledbar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); - str_format(buffer, sizeof(buffer), "%d:%02d / %d:%02d", - current_tick/SERVER_TICK_SPEED/60, (current_tick/SERVER_TICK_SPEED)%60, - total_ticks/SERVER_TICK_SPEED/60, (total_ticks/SERVER_TICK_SPEED)%60); - UI()->DoLabel(&seekbar, buffer, seekbar.h*0.70f, 0); + str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d", + CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60, + TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60); + UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0); // do the logic - int inside = UI()->MouseInside(&seekbar); + int Inside = UI()->MouseInside(&SeekBar); if(UI()->ActiveItem() == id) { @@ -88,13 +84,15 @@ void MENUS::render_demoplayer(CUIRect main_view) UI()->SetActiveItem(0); else { - float amount = (UI()->MouseX()-seekbar.x)/(float)seekbar.w; - if(amount > 0 && amount < 1.0f) + static float PrevAmount = 0.0f; + float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w; + if(Amount > 0 && Amount < 1.0f && PrevAmount != Amount) { - gameclient.on_reset(); - gameclient.suppress_events = true; - client_demoplayer_setpos(amount); - gameclient.suppress_events = false; + PrevAmount = Amount; + m_pClient->OnReset(); + m_pClient->m_SuppressEvents = true; + DemoPlayer()->SetPos(Amount); + m_pClient->m_SuppressEvents = false; } } } @@ -104,334 +102,357 @@ void MENUS::render_demoplayer(CUIRect main_view) UI()->SetActiveItem(id); } - if(inside) + if(Inside) UI()->SetHotItem(id); } - if(menu_active) + if(m_MenuActive) { // do buttons - CUIRect button; + CUIRect Button; // pause button - buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar); - static int pause_button = 0; - if(DoButton_DemoPlayer(&pause_button, "| |", info->paused, &button)) - client_demoplayer_setpause(!info->paused); + ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); + static int s_PauseButton = 0; + if(DoButton_DemoPlayer(&s_PauseButton, "| |", pInfo->m_Paused, &Button)) + { + if(pInfo->m_Paused) + DemoPlayer()->Unpause(); + else + DemoPlayer()->Pause(); + } // play button - buttonbar.VSplitLeft(margins, 0, &buttonbar); - buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar); - static int play_button = 0; - if(DoButton_DemoPlayer(&play_button, ">", !info->paused, &button)) + ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); + ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); + static int s_PlayButton = 0; + if(DoButton_DemoPlayer(&s_PlayButton, ">", !pInfo->m_Paused, &Button)) { - client_demoplayer_setpause(0); - client_demoplayer_setspeed(1.0f); + DemoPlayer()->Unpause(); + DemoPlayer()->SetSpeed(1.0f); } // slowdown - buttonbar.VSplitLeft(margins, 0, &buttonbar); - buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar); - static int slowdown_button = 0; - if(DoButton_DemoPlayer(&slowdown_button, "<<", 0, &button)) + ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); + ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); + static int s_SlowDownButton = 0; + if(DoButton_DemoPlayer(&s_SlowDownButton, "<<", 0, &Button)) { - if(info->speed > 4.0f) client_demoplayer_setspeed(4.0f); - else if(info->speed > 2.0f) client_demoplayer_setspeed(2.0f); - else if(info->speed > 1.0f) client_demoplayer_setspeed(1.0f); - else if(info->speed > 0.5f) client_demoplayer_setspeed(0.5f); - else client_demoplayer_setspeed(0.05f); + if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f); + else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f); + else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f); + else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f); + else DemoPlayer()->SetSpeed(0.05f); } // fastforward - buttonbar.VSplitLeft(margins, 0, &buttonbar); - buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar); - static int fastforward_button = 0; - if(DoButton_DemoPlayer(&fastforward_button, ">>", 0, &button)) + ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); + ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); + static int s_FastForwardButton = 0; + if(DoButton_DemoPlayer(&s_FastForwardButton, ">>", 0, &Button)) { - if(info->speed < 0.5f) client_demoplayer_setspeed(0.5f); - else if(info->speed < 1.0f) client_demoplayer_setspeed(1.0f); - else if(info->speed < 2.0f) client_demoplayer_setspeed(2.0f); - else if(info->speed < 4.0f) client_demoplayer_setspeed(4.0f); - else client_demoplayer_setspeed(8.0f); + if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f); + else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f); + else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f); + else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f); + else DemoPlayer()->SetSpeed(8.0f); } // speed meter - buttonbar.VSplitLeft(margins*3, 0, &buttonbar); - char buffer[64]; - if(info->speed >= 1.0f) - str_format(buffer, sizeof(buffer), "x%.0f", info->speed); + ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar); + char aBuffer[64]; + if(pInfo->m_Speed >= 1.0f) + str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed); else - str_format(buffer, sizeof(buffer), "x%.1f", info->speed); - UI()->DoLabel(&buttonbar, buffer, button.h*0.7f, -1); + str_format(aBuffer, sizeof(aBuffer), "x%.1f", pInfo->m_Speed); + UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1); // close button - buttonbar.VSplitRight(buttonbar_height*3, &buttonbar, &button); - static int exit_button = 0; - if(DoButton_DemoPlayer(&exit_button, localize("Close"), 0, &button)) - client_disconnect(); + ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button); + static int s_ExitButton = 0; + if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button)) + Client()->Disconnect(); } } -static CUIRect listbox_originalview; -static CUIRect listbox_view; -static float listbox_rowheight; -static int listbox_itemindex; -static int listbox_selected_index; -static int listbox_new_selected; -static int listbox_doneevents; -static int listbox_numitems; - -void MENUS::ui_do_listbox_start(void *id, const CUIRect *rect, float row_height, const char *title, int num_items, int selected_index) +static CUIRect gs_ListBoxOriginalView; +static CUIRect gs_ListBoxView; +static float gs_ListBoxRowHeight; +static int gs_ListBoxItemIndex; +static int gs_ListBoxSelectedIndex; +static int gs_ListBoxNewSelected; +static int gs_ListBoxDoneEvents; +static int gs_ListBoxNumItems; +static int gs_ListBoxItemsPerRow; +static float gs_ListBoxScrollValue; +static bool gs_ListBoxItemActivated; + +void CMenus::UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue) { - CUIRect scroll, row; - CUIRect view = *rect; - CUIRect header, footer; + CUIRect Scroll, Row; + CUIRect View = *pRect; + CUIRect Header, Footer; // draw header - view.HSplitTop(listheader_height, &header, &view); - RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - UI()->DoLabel(&header, title, header.h*fontmod_height, 0); + View.HSplitTop(ms_ListheaderHeight, &Header, &View); + RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); + UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0); // draw footers - view.HSplitBottom(listheader_height, &view, &footer); - RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - footer.VSplitLeft(10.0f, 0, &footer); + View.HSplitBottom(ms_ListheaderHeight, &View, &Footer); + RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); + Footer.VSplitLeft(10.0f, 0, &Footer); + UI()->DoLabel(&Footer, pBottomText, Header.h*ms_FontmodHeight, 0); // background - RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.15f), 0, 0); + RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0); // prepare the scroll - view.VSplitRight(15, &view, &scroll); + View.VSplitRight(15, &View, &Scroll); // setup the variables - listbox_originalview = view; - listbox_selected_index = selected_index; - listbox_new_selected = selected_index; - listbox_itemindex = 0; - listbox_rowheight = row_height; - listbox_numitems = num_items; - listbox_doneevents = 0; - //int num_servers = client_serverbrowse_sorted_num(); - + gs_ListBoxOriginalView = View; + gs_ListBoxSelectedIndex = SelectedIndex; + gs_ListBoxNewSelected = SelectedIndex; + gs_ListBoxItemIndex = 0; + gs_ListBoxRowHeight = RowHeight; + gs_ListBoxNumItems = NumItems; + gs_ListBoxItemsPerRow = ItemsPerRow; + gs_ListBoxDoneEvents = 0; + gs_ListBoxScrollValue = ScrollValue; + gs_ListBoxItemActivated = false; // do the scrollbar - view.HSplitTop(listbox_rowheight, &row, 0); + View.HSplitTop(gs_ListBoxRowHeight, &Row, 0); - int num_viewable = (int)(listbox_originalview.h/row.h) + 1; - int num = num_items-num_viewable+1; - if(num < 0) - num = 0; + int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1; + int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; + if(Num < 0) + Num = 0; + if(Num > 0) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + gs_ListBoxScrollValue -= 1.0f/Num; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + gs_ListBoxScrollValue += 1.0f/Num; - static float scrollvalue = 0; - scroll.HMargin(5.0f, &scroll); - scrollvalue = DoScrollbarV(id, &scroll, scrollvalue); - - int start = (int)(num*scrollvalue); - if(start < 0) - start = 0; + if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; + if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; + } + + Scroll.HMargin(5.0f, &Scroll); + gs_ListBoxScrollValue = DoScrollbarV(pId, &Scroll, gs_ListBoxScrollValue); // the list - listbox_view = listbox_originalview; - listbox_view.VMargin(5.0f, &listbox_view); - UI()->ClipEnable(&listbox_view); - listbox_view.y -= scrollvalue*num*row.h; + gs_ListBoxView = gs_ListBoxOriginalView; + gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView); + UI()->ClipEnable(&gs_ListBoxView); + gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h; } -MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextrow() +CMenus::CListboxItem CMenus::UiDoListboxNextRow() { - LISTBOXITEM item = {0}; - listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &item.rect, &listbox_view); - item.visible = 1; + static CUIRect s_RowView; + CListboxItem Item = {0}; + if(gs_ListBoxItemIndex%gs_ListBoxItemsPerRow == 0) + gs_ListBoxView.HSplitTop(gs_ListBoxRowHeight /*-2.0f*/, &s_RowView, &gs_ListBoxView); + + s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView); + + Item.m_Visible = 1; //item.rect = row; - item.hitrect = item.rect; + Item.m_HitRect = Item.m_Rect; //CUIRect select_hit_box = item.rect; - if(listbox_selected_index == listbox_itemindex) - item.selected = 1; + if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex) + Item.m_Selected = 1; // make sure that only those in view can be selected - if(item.rect.y+item.rect.h > listbox_originalview.y) + if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y) { - if(item.hitrect.y < item.hitrect.y) // clip the selection + if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection { - item.hitrect.h -= listbox_originalview.y-item.hitrect.y; - item.hitrect.y = listbox_originalview.y; + Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y; + Item.m_HitRect.y = gs_ListBoxOriginalView.y; } } else - item.visible = 0; + Item.m_Visible = 0; // check if we need to do more - if(item.rect.y > listbox_originalview.y+listbox_originalview.h) - item.visible = 0; + if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h) + Item.m_Visible = 0; - listbox_itemindex++; - return item; + gs_ListBoxItemIndex++; + return Item; } -MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextitem(void *id) +CMenus::CListboxItem CMenus::UiDoListboxNextItem(void *pId, bool Selected) { - int this_itemindex = listbox_itemindex; - - LISTBOXITEM item = ui_do_listbox_nextrow(); - - if(UI()->DoButtonLogic(id, "", listbox_selected_index == listbox_itemindex, &item.hitrect)) - listbox_new_selected = listbox_itemindex; - - //CUIRect row; - //LISTBOXITEM item = {0}; - //listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &row, &listbox_view); - //listbox_view.HSplitTop(2.0f, 0, &listbox_view); - /* - CUIRect select_hit_box = row; - - item.visible = 1; - if(listbox_selected_index == listbox_itemindex) - item.selected = 1; - - // make sure that only those in view can be selected - if(row.y+row.h > listbox_originalview.y) + int ThisItemIndex = gs_ListBoxItemIndex; + if(Selected) { - - if(select_hit_box.y < listbox_originalview.y) // clip the selection - { - select_hit_box.h -= listbox_originalview.y-select_hit_box.y; - select_hit_box.y = listbox_originalview.y; - } - - if(UI()->DoButton(id, "", listbox_selected_index==listbox_itemindex, &select_hit_box, 0, 0)) - listbox_new_selected = listbox_itemindex; + if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected) + gs_ListBoxNewSelected = ThisItemIndex; + gs_ListBoxSelectedIndex = ThisItemIndex; } - else - item.visible = 0; - - item.rect = row; - */ + CListboxItem Item = UiDoListboxNextRow(); - if(listbox_selected_index == this_itemindex) + if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect)) + gs_ListBoxNewSelected = ThisItemIndex; + + // process input, regard selected index + if(gs_ListBoxSelectedIndex == ThisItemIndex) { - if(!listbox_doneevents) + if(!gs_ListBoxDoneEvents) { - listbox_doneevents = 1; - - for(int i = 0; i < num_inputevents; i++) + gs_ListBoxDoneEvents = 1; + + if(m_EnterPressed || (Input()->MouseDoubleClick() && UI()->ActiveItem() == pId)) { - if(inputevents[i].flags&INPFLAG_PRESS) + gs_ListBoxItemActivated = true; + } + else + { + for(int i = 0; i < m_NumInputEvents; i++) { - if(inputevents[i].key == KEY_DOWN) listbox_new_selected++; - if(inputevents[i].key == KEY_UP) listbox_new_selected--; + int NewIndex = -1; + if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS) + { + if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = gs_ListBoxNewSelected + 1; + if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = gs_ListBoxNewSelected - 1; + } + if(NewIndex > -1 && NewIndex < gs_ListBoxNumItems) + { + // scroll + int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1; + int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; + if(ScrollNum > 0 && NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxSelectedIndex/gs_ListBoxItemsPerRow) + { + // TODO: make the scrolling better + if(NewIndex - gs_ListBoxSelectedIndex > 0) + gs_ListBoxScrollValue += 1.0f/ScrollNum; + else + gs_ListBoxScrollValue -= 1.0f/ScrollNum; + if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; + if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; + } + + gs_ListBoxNewSelected = NewIndex; + } } } - - if(listbox_new_selected >= listbox_numitems) - listbox_new_selected = listbox_numitems-1; - if(listbox_new_selected < 0) - listbox_new_selected = 0; } //selected_index = i; - CUIRect r = item.rect; + CUIRect r = Item.m_Rect; r.Margin(1.5f, &r); RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); } - //listbox_itemindex++; - return item; + return Item; } -int MENUS::ui_do_listbox_end() +int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated) { UI()->ClipDisable(); - return listbox_new_selected; + if(pScrollValue) + *pScrollValue = gs_ListBoxScrollValue; + if(pItemActivated) + *pItemActivated = gs_ListBoxItemActivated; + return gs_ListBoxNewSelected; } struct FETCH_CALLBACKINFO { - MENUS *self; - const char *prefix; - int count; + CMenus *m_pSelf; + const char *m_pPrefix; + int m_Count; }; -void MENUS::demolist_fetch_callback(const char *name, int is_dir, void *user) +void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser) { - if(is_dir || name[0] == '.') + if(IsDir || pName[0] == '.') return; - FETCH_CALLBACKINFO *info = (FETCH_CALLBACKINFO *)user; + FETCH_CALLBACKINFO *pInfo = (FETCH_CALLBACKINFO *)pUser; - DEMOITEM item; - str_format(item.filename, sizeof(item.filename), "%s/%s", info->prefix, name); - str_copy(item.name, name, sizeof(item.name)); - info->self->demos.add(item); + CDemoItem Item; + str_format(Item.m_aFilename, sizeof(Item.m_aFilename), "%s/%s", pInfo->m_pPrefix, pName); + str_copy(Item.m_aName, pName, sizeof(Item.m_aName)); + pInfo->m_pSelf->m_lDemos.add(Item); } -void MENUS::demolist_populate() +void CMenus::DemolistPopulate() { - demos.clear(); + m_lDemos.clear(); - char buf[512]; - str_format(buf, sizeof(buf), "%s/demos", client_user_directory()); + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "%s/demos", Client()->UserDirectory()); - FETCH_CALLBACKINFO info = {this, buf, 0}; - fs_listdir(buf, demolist_fetch_callback, &info); - info.prefix = "demos"; - fs_listdir("demos", demolist_fetch_callback, &info); + FETCH_CALLBACKINFO Info = {this, aBuf, 0}; + fs_listdir(aBuf, DemolistFetchCallback, &Info); + Info.m_pPrefix = "demos"; + fs_listdir("demos", DemolistFetchCallback, &Info); } -void MENUS::render_demolist(CUIRect main_view) +void CMenus::RenderDemoList(CUIRect MainView) { - static int inited = 0; - if(!inited) - demolist_populate(); - inited = 1; + static int s_Inited = 0; + if(!s_Inited) + DemolistPopulate(); + s_Inited = 1; // render background - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f); - main_view.Margin(10.0f, &main_view); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); + MainView.Margin(10.0f, &MainView); - CUIRect buttonbar; - main_view.HSplitBottom(button_height+5.0f, &main_view, &buttonbar); - buttonbar.HSplitTop(5.0f, 0, &buttonbar); + CUIRect ButtonBar; + MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar); + ButtonBar.HSplitTop(5.0f, 0, &ButtonBar); - static int selected_item = -1; - static int demolist_id = 0; + static int s_SelectedItem = -1; + static int s_DemoListId = 0; + static float s_ScrollValue = 0; - ui_do_listbox_start(&demolist_id, &main_view, 17.0f, localize("Demos"), demos.size(), selected_item); + UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), "", m_lDemos.size(), 1, s_SelectedItem, s_ScrollValue); //for(int i = 0; i < num_demos; i++) - for(sorted_array<DEMOITEM>::range r = demos.all(); !r.empty(); r.pop_front()) + for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { - LISTBOXITEM item = ui_do_listbox_nextitem((void*)(&r.front())); - if(item.visible) - UI()->DoLabel(&item.rect, r.front().name, item.rect.h*fontmod_height, -1); + CListboxItem Item = UiDoListboxNextItem((void*)(&r.front())); + if(Item.m_Visible) + UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1); } - selected_item = ui_do_listbox_end(); - - CUIRect refresh_rect, play_rect; - buttonbar.VSplitRight(250.0f, &buttonbar, &refresh_rect); - refresh_rect.VSplitRight(130.0f, &refresh_rect, &play_rect); - play_rect.VSplitRight(120.0f, 0x0, &play_rect); + bool Activated = false; + s_SelectedItem = UiDoListboxEnd(&s_ScrollValue, &Activated); - static int refresh_button = 0; - if(DoButton_Menu(&refresh_button, localize("Refresh"), 0, &refresh_rect)) - { - demolist_populate(); - } + CUIRect RefreshRect, PlayRect; + ButtonBar.VSplitRight(250.0f, &ButtonBar, &RefreshRect); + RefreshRect.VSplitRight(130.0f, &RefreshRect, &PlayRect); + PlayRect.VSplitRight(120.0f, 0x0, &PlayRect); - static int play_button = 0; - if(DoButton_Menu(&play_button, localize("Play"), 0, &play_rect)) + static int s_RefreshButton = 0; + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect)) { - if(selected_item >= 0 && selected_item < demos.size()) + DemolistPopulate(); + } + + static int s_PlayButton = 0; + if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &PlayRect) || Activated) + { + if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size()) { - const char *error = client_demoplayer_play(demos[selected_item].filename); - if(error) - popup_message(localize("Error"), error, localize("Ok")); + const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename); + if(pError) + PopupMessage(Localize("Error"), pError, Localize("Ok")); } } diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index d31a15bd..7d1f2513 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -1,89 +1,90 @@ -#include <base/math.hpp> +#include <base/math.h> -#include <string.h> // strcmp, strlen, strncpy -#include <stdlib.h> // atoi -#include <engine/e_client_interface.h> +#include <engine/serverbrowser.h> +#include <engine/textrender.h> +#include <engine/shared/config.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/ui.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> +#include <game/client/ui.h> +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include <game/localization.h> -#include "menus.hpp" -#include "motd.hpp" -#include "voting.hpp" +#include "menus.h" +#include "motd.h" +#include "voting.h" -void MENUS::render_game(CUIRect main_view) +void CMenus::RenderGame(CUIRect MainView) { - CUIRect button; + CUIRect Button; //CUIRect votearea; - main_view.HSplitTop(45.0f, &main_view, 0); - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f); + MainView.HSplitTop(45.0f, &MainView, 0); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); - main_view.HSplitTop(10.0f, 0, &main_view); - main_view.HSplitTop(25.0f, &main_view, 0); - main_view.VMargin(10.0f, &main_view); + MainView.HSplitTop(10.0f, 0, &MainView); + MainView.HSplitTop(25.0f, &MainView, 0); + MainView.VMargin(10.0f, &MainView); - main_view.VSplitRight(120.0f, &main_view, &button); - static int disconnect_button = 0; - if(DoButton_Menu(&disconnect_button, localize("Disconnect"), 0, &button)) - client_disconnect(); + MainView.VSplitRight(120.0f, &MainView, &Button); + static int s_DisconnectButton = 0; + if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button)) + Client()->Disconnect(); - if(gameclient.snap.local_info && gameclient.snap.gameobj) + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pGameobj) { - if(gameclient.snap.local_info->team != -1) + if(m_pClient->m_Snap.m_pLocalInfo->m_Team != -1) { - main_view.VSplitLeft(10.0f, &button, &main_view); - main_view.VSplitLeft(120.0f, &button, &main_view); - static int spectate_button = 0; - if(DoButton_Menu(&spectate_button, localize("Spectate"), 0, &button)) + MainView.VSplitLeft(10.0f, &Button, &MainView); + MainView.VSplitLeft(120.0f, &Button, &MainView); + static int s_SpectateButton = 0; + if(DoButton_Menu(&s_SpectateButton, Localize("Spectate"), 0, &Button)) { - gameclient.send_switch_team(-1); - set_active(false); + m_pClient->SendSwitchTeam(-1); + SetActive(false); } } - if(gameclient.snap.gameobj->flags & GAMEFLAG_TEAMS) + if(m_pClient->m_Snap.m_pGameobj->m_Flags & GAMEFLAG_TEAMS) { - if(gameclient.snap.local_info->team != 0) + if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 0) { - main_view.VSplitLeft(10.0f, &button, &main_view); - main_view.VSplitLeft(120.0f, &button, &main_view); - static int spectate_button = 0; - if(DoButton_Menu(&spectate_button, localize("Join red"), 0, &button)) + MainView.VSplitLeft(10.0f, &Button, &MainView); + MainView.VSplitLeft(120.0f, &Button, &MainView); + static int s_SpectateButton = 0; + if(DoButton_Menu(&s_SpectateButton, Localize("Join red"), 0, &Button)) { - gameclient.send_switch_team(0); - set_active(false); + m_pClient->SendSwitchTeam(0); + SetActive(false); } } - if(gameclient.snap.local_info->team != 1) + if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 1) { - main_view.VSplitLeft(10.0f, &button, &main_view); - main_view.VSplitLeft(120.0f, &button, &main_view); - static int spectate_button = 0; - if(DoButton_Menu(&spectate_button, localize("Join blue"), 0, &button)) + MainView.VSplitLeft(10.0f, &Button, &MainView); + MainView.VSplitLeft(120.0f, &Button, &MainView); + static int s_SpectateButton = 0; + if(DoButton_Menu(&s_SpectateButton, Localize("Join blue"), 0, &Button)) { - gameclient.send_switch_team(1); - set_active(false); + m_pClient->SendSwitchTeam(1); + SetActive(false); } } } else { - if(gameclient.snap.local_info->team != 0) + if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 0) { - main_view.VSplitLeft(10.0f, &button, &main_view); - main_view.VSplitLeft(120.0f, &button, &main_view); - static int spectate_button = 0; - if(DoButton_Menu(&spectate_button, localize("Join game"), 0, &button)) + MainView.VSplitLeft(10.0f, &Button, &MainView); + MainView.VSplitLeft(120.0f, &Button, &MainView); + static int s_SpectateButton = 0; + if(DoButton_Menu(&s_SpectateButton, Localize("Join game"), 0, &Button)) { - gameclient.send_switch_team(0); - set_active(false); + m_pClient->SendSwitchTeam(0); + SetActive(false); } } } @@ -141,102 +142,102 @@ void MENUS::render_game(CUIRect main_view) }*/ } -void MENUS::render_serverinfo(CUIRect main_view) +void CMenus::RenderServerInfo(CUIRect MainView) { // fetch server info - SERVER_INFO current_server_info; - client_serverinfo(¤t_server_info); + CServerInfo CurrentServerInfo; + Client()->GetServerInfo(&CurrentServerInfo); - if(!gameclient.snap.local_info) + if(!m_pClient->m_Snap.m_pLocalInfo) return; // count players for server info-box - int num_players = 0; - for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) + int NumPlayers = 0; + for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++) { - SNAP_ITEM item; - snap_get_item(SNAP_CURRENT, i, &item); + IClient::CSnapItem Item; + Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - if(item.type == NETOBJTYPE_PLAYER_INFO) + if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { - num_players++; + NumPlayers++; } } // render background - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); - CUIRect view, serverinfo, gameinfo, motd; + CUIRect View, ServerInfo, GameInfo, Motd; float x = 0.0f; float y = 0.0f; - char buf[1024]; + char aBuf[1024]; // set view to use for all sub-modules - main_view.Margin(10.0f, &view); + MainView.Margin(10.0f, &View); - /* serverinfo */ - view.HSplitTop(view.h/2-5.0f, &serverinfo, &motd); - serverinfo.VSplitLeft(view.w/2-5.0f, &serverinfo, &gameinfo); - RenderTools()->DrawUIRect(&serverinfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + // serverinfo + View.HSplitTop(View.h/2-5.0f, &ServerInfo, &Motd); + ServerInfo.VSplitLeft(View.w/2-5.0f, &ServerInfo, &GameInfo); + RenderTools()->DrawUIRect(&ServerInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - serverinfo.Margin(5.0f, &serverinfo); + ServerInfo.Margin(5.0f, &ServerInfo); x = 5.0f; y = 0.0f; - gfx_text(0, serverinfo.x+x, serverinfo.y+y, 32, localize("Server info"), 250); + TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 32, Localize("Server info"), 250); y += 32.0f+5.0f; - mem_zero(buf, sizeof(buf)); + mem_zero(aBuf, sizeof(aBuf)); str_format( - buf, - sizeof(buf), + aBuf, + sizeof(aBuf), "%s\n\n" "%s: %s\n" "%s: %d\n" "%s: %s\n" "%s: %s\n", - current_server_info.name, - localize("Address"), config.ui_server_address, - localize("Ping"), gameclient.snap.local_info->latency, - localize("Version"), current_server_info.version, - localize("Password"), current_server_info.flags&1 ? localize("Yes") : localize("No") + CurrentServerInfo.m_aName, + Localize("Address"), g_Config.m_UiServerAddress, + Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency, + Localize("Version"), CurrentServerInfo.m_aVersion, + Localize("Password"), CurrentServerInfo.m_Flags &1 ? Localize("Yes") : Localize("No") ); - gfx_text(0, serverinfo.x+x, serverinfo.y+y, 20, buf, 250); + TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 20, aBuf, 250); { - CUIRect button; - int is_favorite = client_serverbrowse_isfavorite(current_server_info.netaddr); - serverinfo.HSplitBottom(20.0f, &serverinfo, &button); - static int add_fav_button = 0; - if(DoButton_CheckBox(&add_fav_button, localize("Favorite"), is_favorite, &button)) + CUIRect Button; + int IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr); + ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button); + static int s_AddFavButton = 0; + if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Button)) { - if(is_favorite) - client_serverbrowse_removefavorite(current_server_info.netaddr); + if(IsFavorite) + ServerBrowser()->RemoveFavorite(CurrentServerInfo.m_NetAddr); else - client_serverbrowse_addfavorite(current_server_info.netaddr); + ServerBrowser()->AddFavorite(CurrentServerInfo.m_NetAddr); } } - /* gameinfo */ - gameinfo.VSplitLeft(10.0f, 0x0, &gameinfo); - RenderTools()->DrawUIRect(&gameinfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + // gameinfo + GameInfo.VSplitLeft(10.0f, 0x0, &GameInfo); + RenderTools()->DrawUIRect(&GameInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - gameinfo.Margin(5.0f, &gameinfo); + GameInfo.Margin(5.0f, &GameInfo); x = 5.0f; y = 0.0f; - gfx_text(0, gameinfo.x+x, gameinfo.y+y, 32, localize("Game info"), 250); + TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 32, Localize("Game info"), 250); y += 32.0f+5.0f; - mem_zero(buf, sizeof(buf)); + mem_zero(aBuf, sizeof(aBuf)); str_format( - buf, - sizeof(buf), + aBuf, + sizeof(aBuf), "\n\n" "%s: %s\n" "%s: %s\n" @@ -244,153 +245,178 @@ void MENUS::render_serverinfo(CUIRect main_view) "%s: %d\n" "\n" "%s: %d/%d\n", - localize("Game type"), current_server_info.gametype, - localize("Map"), current_server_info.map, - localize("Score limit"), gameclient.snap.gameobj->score_limit, - localize("Time limit"), gameclient.snap.gameobj->time_limit, - localize("Players"), gameclient.snap.num_players, current_server_info.max_players + Localize("Game type"), CurrentServerInfo.m_aGameType, + Localize("Map"), CurrentServerInfo.m_aMap, + Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit, + Localize("Time limit"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit, + Localize("Players"), m_pClient->m_Snap.m_NumPlayers, CurrentServerInfo.m_MaxPlayers ); - gfx_text(0, gameinfo.x+x, gameinfo.y+y, 20, buf, 250); + TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 20, aBuf, 250); - /* motd */ - motd.HSplitTop(10.0f, 0, &motd); - RenderTools()->DrawUIRect(&motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - motd.Margin(5.0f, &motd); + // motd + Motd.HSplitTop(10.0f, 0, &Motd); + RenderTools()->DrawUIRect(&Motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + Motd.Margin(5.0f, &Motd); y = 0.0f; x = 5.0f; - gfx_text(0, motd.x+x, motd.y+y, 32, localize("MOTD"), -1); + TextRender()->Text(0, Motd.x+x, Motd.y+y, 32, Localize("MOTD"), -1); y += 32.0f+5.0f; - gfx_text(0, motd.x+x, motd.y+y, 16, gameclient.motd->server_motd, (int)motd.w); + TextRender()->Text(0, Motd.x+x, Motd.y+y, 16, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w); } -static const char *format_command(const char *cmd) +static const char *FormatCommand(const char *pCmd) { - return cmd; + return pCmd; } -void MENUS::render_servercontrol_server(CUIRect main_view) +void CMenus::RenderServerControlServer(CUIRect MainView) { - int num_options = 0; - for(VOTING::VOTEOPTION *option = gameclient.voting->first; option; option = option->next) - num_options++; - - static int votelist = 0; - CUIRect list = main_view; - ui_do_listbox_start(&votelist, &list, 24.0f, localize("Settings"), num_options, callvote_selectedoption); + int NumOptions = 0; + for(CVoting::CVoteOption *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) + NumOptions++; + + static int s_VoteList = 0; + static float s_ScrollValue = 0; + CUIRect List = MainView; + UiDoListboxStart(&s_VoteList, &List, 24.0f, Localize("Settings"), "", NumOptions, 1, m_CallvoteSelectedOption, s_ScrollValue); - for(VOTING::VOTEOPTION *option = gameclient.voting->first; option; option = option->next) + for(CVoting::CVoteOption *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { - LISTBOXITEM item = ui_do_listbox_nextitem(option); + CListboxItem Item = UiDoListboxNextItem(pOption); - if(item.visible) - UI()->DoLabel(&item.rect, format_command(option->command), 16.0f, -1); + if(Item.m_Visible) + UI()->DoLabel(&Item.m_Rect, FormatCommand(pOption->m_aCommand), 16.0f, -1); } - callvote_selectedoption = ui_do_listbox_end(); + m_CallvoteSelectedOption = UiDoListboxEnd(&s_ScrollValue, 0); } -void MENUS::render_servercontrol_kick(CUIRect main_view) +void CMenus::RenderServerControlKick(CUIRect MainView) { // draw header - CUIRect header, footer; - main_view.HSplitTop(20, &header, &main_view); - RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - UI()->DoLabel(&header, localize("Players"), 18.0f, 0); + CUIRect Header, Footer; + MainView.HSplitTop(20, &Header, &MainView); + RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); + UI()->DoLabel(&Header, Localize("Players"), 18.0f, 0); // draw footers - main_view.HSplitBottom(20, &main_view, &footer); - RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - footer.VSplitLeft(10.0f, 0, &footer); + MainView.HSplitBottom(20, &MainView, &Footer); + RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); + Footer.VSplitLeft(10.0f, 0, &Footer); // players - RenderTools()->DrawUIRect(&main_view, vec4(0,0,0,0.15f), 0, 0); - CUIRect list = main_view; + RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), 0, 0); + CUIRect List = MainView; for(int i = 0; i < MAX_CLIENTS; i++) { - if(!gameclient.snap.player_infos[i]) + if(!m_pClient->m_Snap.m_paPlayerInfos[i]) continue; - CUIRect button; - list.HSplitTop(button_height, &button, &list); + CUIRect Button; + List.HSplitTop(ms_ButtonHeight, &Button, &List); - if(DoButton_ListRow((char *)&gameclient.snap+i, "", callvote_selectedplayer == i, &button)) - callvote_selectedplayer = i; + if(DoButton_ListRow((char *)&m_pClient->m_Snap+i, "", m_CallvoteSelectedPlayer == i, &Button)) + m_CallvoteSelectedPlayer = i; - TEE_RENDER_INFO info = gameclient.clients[i].render_info; - info.size = button.h; - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0), vec2(button.x+button.h/2, button.y+button.h/2)); + CTeeRenderInfo Info = m_pClient->m_aClients[i].m_RenderInfo; + Info.m_Size = Button.h; + RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Button.x+Button.h/2, Button.y+Button.h/2)); - button.x += button.h; - UI()->DoLabel(&button, gameclient.clients[i].name, 18.0f, -1); + Button.x += Button.h; + UI()->DoLabel(&Button, m_pClient->m_aClients[i].m_aName, 18.0f, -1); } } -void MENUS::render_servercontrol(CUIRect main_view) +void CMenus::RenderServerControl(CUIRect MainView) { - static int control_page = 0; + static int s_ControlPage = 0; // render background - CUIRect temp, tabbar; - main_view.VSplitRight(120.0f, &main_view, &tabbar); - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); - tabbar.HSplitTop(50.0f, &temp, &tabbar); - RenderTools()->DrawUIRect(&temp, color_tabbar_active, CUI::CORNER_R, 10.0f); + CUIRect Temp, TabBar; + MainView.VSplitRight(120.0f, &MainView, &TabBar); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); + TabBar.HSplitTop(50.0f, &Temp, &TabBar); + RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f); - main_view.HSplitTop(10.0f, 0, &main_view); + MainView.HSplitTop(10.0f, 0, &MainView); - CUIRect button; + CUIRect Button; - const char *tabs[] = { - localize("Settings"), - localize("Kick")}; - int num_tabs = (int)(sizeof(tabs)/sizeof(*tabs)); + const char *paTabs[] = { + Localize("Settings"), + Localize("Kick")}; + int aNumTabs = (int)(sizeof(paTabs)/sizeof(*paTabs)); - for(int i = 0; i < num_tabs; i++) + for(int i = 0; i < aNumTabs; i++) { - tabbar.HSplitTop(10, &button, &tabbar); - tabbar.HSplitTop(26, &button, &tabbar); - if(DoButton_SettingsTab(tabs[i], tabs[i], control_page == i, &button)) + TabBar.HSplitTop(10, &Button, &TabBar); + TabBar.HSplitTop(26, &Button, &TabBar); + if(DoButton_SettingsTab(paTabs[i], paTabs[i], s_ControlPage == i, &Button)) { - control_page = i; - callvote_selectedplayer = -1; - callvote_selectedoption = -1; + s_ControlPage = i; + m_CallvoteSelectedPlayer = -1; + m_CallvoteSelectedOption = -1; } } - main_view.Margin(10.0f, &main_view); - CUIRect bottom; - main_view.HSplitBottom(button_height + 5*2, &main_view, &bottom); - bottom.HMargin(5.0f, &bottom); + MainView.Margin(10.0f, &MainView); + CUIRect Bottom; + MainView.HSplitBottom(ms_ButtonHeight + 5*2, &MainView, &Bottom); + Bottom.HMargin(5.0f, &Bottom); // render page - if(control_page == 0) - render_servercontrol_server(main_view); - else if(control_page == 1) - render_servercontrol_kick(main_view); + if(s_ControlPage == 0) + RenderServerControlServer(MainView); + else if(s_ControlPage == 1) + RenderServerControlKick(MainView); { - CUIRect button; - bottom.VSplitRight(120.0f, &bottom, &button); + CUIRect Button; + Bottom.VSplitRight(120.0f, &Bottom, &Button); - static int callvote_button = 0; - if(DoButton_Menu(&callvote_button, localize("Call vote"), 0, &button)) + static int s_CallVoteButton = 0; + if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button)) { - if(control_page == 0) + if(s_ControlPage == 0) { // - gameclient.voting->callvote_option(callvote_selectedoption); + m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption); /* if(callvote_selectedmap >= 0 && callvote_selectedmap < gameclient.maplist->num()) gameclient.voting->callvote_map(gameclient.maplist->name(callvote_selectedmap));*/ } - else if(control_page == 1) + else if(s_ControlPage == 1) + { + if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS && + m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer]) + { + m_pClient->m_pVoting->CallvoteKick(m_CallvoteSelectedPlayer); + SetActive(false); + } + } + } + + // force vote button (only available when authed in rcon) + if(Client()->RconAuthed()) + { + Bottom.VSplitLeft(120.0f, &Button, &Bottom); + + static int s_ForceVoteButton = 0; + if(DoButton_Menu(&s_ForceVoteButton, Localize("Force vote"), 0, &Button)) { - if(callvote_selectedplayer >= 0 && callvote_selectedplayer < MAX_CLIENTS && - gameclient.snap.player_infos[callvote_selectedplayer]) + if(s_ControlPage == 0) + { + m_pClient->m_pVoting->ForcevoteOption(m_CallvoteSelectedOption); + } + else if(s_ControlPage == 1) { - gameclient.voting->callvote_kick(callvote_selectedplayer); - set_active(false); + if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS && + m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer]) + { + m_pClient->m_pVoting->ForcevoteKick(m_CallvoteSelectedPlayer); + SetActive(false); + } } } } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 05b4d047..a612ed77 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1,821 +1,752 @@ -#include <base/math.hpp> +#include <base/math.h> -#include <string.h> // strcmp, strlen, strncpy -#include <stdlib.h> // atoi -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/shared/config.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/ui.hpp> -#include <game/client/render.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include <game/localization.hpp> +#include <game/client/ui.h> +#include <game/client/render.h> +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include <game/localization.h> -#include "binds.hpp" -#include "menus.hpp" -#include "skins.hpp" +#include "binds.h" +#include "menus.h" +#include "skins.h" -MENUS_KEYBINDER MENUS::binder; +CMenusKeyBinder CMenus::m_Binder; -MENUS_KEYBINDER::MENUS_KEYBINDER() +CMenusKeyBinder::CMenusKeyBinder() { - take_key = false; - got_key = false; + m_TakeKey = false; + m_GotKey = false; } -bool MENUS_KEYBINDER::on_input(INPUT_EVENT e) +bool CMenusKeyBinder::OnInput(IInput::CEvent Event) { - if(take_key) + if(m_TakeKey) { - if(e.flags&INPFLAG_PRESS && e.key != KEY_ESCAPE) + if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key != KEY_ESCAPE) { - key = e; - got_key = true; - take_key = false; + m_Key = Event; + m_GotKey = true; + m_TakeKey = false; } return true; } - + return false; } -void MENUS::render_settings_player(CUIRect main_view) +void CMenus::RenderSettingsPlayer(CUIRect MainView) { - CUIRect button; - CUIRect othersection; - main_view.VSplitLeft(300.0f, &main_view, &othersection); - main_view.HSplitTop(20.0f, &button, &main_view); + CUIRect Button; + CUIRect LeftView, RightView; + + MainView.VSplitLeft(MainView.w/2, &LeftView, &RightView); + LeftView.HSplitTop(20.0f, &Button, &LeftView); // render settings - { - char buf[128]; - - main_view.HSplitTop(20.0f, &button, &main_view); - str_format(buf, sizeof(buf), "%s:", localize("Name")); - UI()->DoLabel(&button, buf, 14.0, -1); - button.VSplitLeft(80.0f, 0, &button); - button.VSplitLeft(180.0f, &button, 0); - if(DoEditBox(config.player_name, &button, config.player_name, sizeof(config.player_name), 14.0f)) - need_sendinfo = true; + { + char aBuf[128]; + + LeftView.HSplitTop(20.0f, &Button, &LeftView); + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name")); + UI()->DoLabel(&Button, aBuf, 14.0, -1); + Button.VSplitLeft(80.0f, 0, &Button); + Button.VSplitLeft(180.0f, &Button, 0); + if(DoEditBox(g_Config.m_PlayerName, &Button, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 14.0f)) + m_NeedSendinfo = true; // extra spacing - main_view.HSplitTop(10.0f, 0, &main_view); + LeftView.HSplitTop(10.0f, 0, &LeftView); - static int dynamic_camera_button = 0; - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&dynamic_camera_button, localize("Dynamic Camera"), config.cl_mouse_deadzone != 0, &button)) + static int s_DynamicCameraButton = 0; + LeftView.HSplitTop(20.0f, &Button, &LeftView); + if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button)) { - - if(config.cl_mouse_deadzone) + + if(g_Config.m_ClMouseDeadzone) { - config.cl_mouse_followfactor = 0; - config.cl_mouse_max_distance = 400; - config.cl_mouse_deadzone = 0; + g_Config.m_ClMouseFollowfactor = 0; + g_Config.m_ClMouseMaxDistance = 400; + g_Config.m_ClMouseDeadzone = 0; } else { - config.cl_mouse_followfactor = 60; - config.cl_mouse_max_distance = 1000; - config.cl_mouse_deadzone = 300; + g_Config.m_ClMouseFollowfactor = 60; + g_Config.m_ClMouseMaxDistance = 1000; + g_Config.m_ClMouseDeadzone = 300; } } - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.cl_autoswitch_weapons, localize("Switch weapon on pickup"), config.cl_autoswitch_weapons, &button)) - config.cl_autoswitch_weapons ^= 1; - - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.cl_nameplates, localize("Show name plates"), config.cl_nameplates, &button)) - config.cl_nameplates ^= 1; + LeftView.HSplitTop(20.0f, &Button, &LeftView); + if(DoButton_CheckBox(&g_Config.m_ClAutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button)) + g_Config.m_ClAutoswitchWeapons ^= 1; + + LeftView.HSplitTop(20.0f, &Button, &LeftView); + if(DoButton_CheckBox(&g_Config.m_ClNameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button)) + g_Config.m_ClNameplates ^= 1; //if(config.cl_nameplates) { - main_view.HSplitTop(20.0f, &button, &main_view); - button.VSplitLeft(15.0f, 0, &button); - if(DoButton_CheckBox(&config.cl_nameplates_always, localize("Always show name plates"), config.cl_nameplates_always, &button)) - config.cl_nameplates_always ^= 1; + LeftView.HSplitTop(20.0f, &Button, &LeftView); + Button.VSplitLeft(15.0f, 0, &Button); + if(DoButton_CheckBox(&g_Config.m_ClNameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button)) + g_Config.m_ClNameplatesAlways ^= 1; } - - main_view.HSplitTop(20.0f, &button, &main_view); - - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.player_color_body, localize("Custom colors"), config.player_use_custom_color, &button)) + + { + const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(max(0, m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin))); + + CTeeRenderInfo OwnSkinInfo; + OwnSkinInfo.m_Texture = pOwnSkin->m_OrgTexture; + OwnSkinInfo.m_ColorBody = vec4(1, 1, 1, 1); + OwnSkinInfo.m_ColorFeet = vec4(1, 1, 1, 1); + + if(g_Config.m_PlayerUseCustomColor) + { + OwnSkinInfo.m_ColorBody = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorBody); + OwnSkinInfo.m_ColorFeet = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorFeet); + OwnSkinInfo.m_Texture = pOwnSkin->m_ColorTexture; + } + + OwnSkinInfo.m_Size = UI()->Scale()*50.0f; + + LeftView.HSplitTop(20.0f, &Button, &LeftView); + LeftView.HSplitTop(20.0f, &Button, &LeftView); + + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Your skin")); + UI()->DoLabel(&Button, aBuf, 14.0, -1); + + CUIRect SkinRect; + LeftView.VSplitLeft(LeftView.w/1.2f, &SkinRect, 0); + SkinRect.HSplitTop(50.0f, &SkinRect, 0); + RenderTools()->DrawUIRect(&SkinRect, vec4(1, 1, 1, 0.25f), CUI::CORNER_ALL, 10.0f); + + Button.VSplitLeft(30.0f, 0, &Button); + Button.HSplitTop(50.0f, 0, &Button); + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Button.x, Button.y)); + + LeftView.HSplitTop(20.0f, &Button, &LeftView); + Button.HSplitTop(15.0f, 0, &Button); + Button.VSplitLeft(100.0f, 0, &Button); + + str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_PlayerSkin); + UI()->DoLabel(&Button, aBuf, 14.0, -1); + } + + RightView.HSplitTop(20.0f, &Button, &RightView); + RightView.HSplitTop(20.0f, &Button, &RightView); + + if(DoButton_CheckBox(&g_Config.m_PlayerColorBody, Localize("Custom colors"), g_Config.m_PlayerUseCustomColor, &Button)) { - config.player_use_custom_color = config.player_use_custom_color?0:1; - need_sendinfo = true; + g_Config.m_PlayerUseCustomColor = g_Config.m_PlayerUseCustomColor?0:1; + m_NeedSendinfo = true; } - - if(config.player_use_custom_color) + + if(g_Config.m_PlayerUseCustomColor) { - int *colors[2]; - colors[0] = &config.player_color_body; - colors[1] = &config.player_color_feet; - - const char *parts[] = { - localize("Body"), - localize("Feet")}; - const char *labels[] = { - localize("Hue"), - localize("Sat."), - localize("Lht.")}; - static int color_slider[2][3] = {{0}}; + int *paColors[2]; + paColors[0] = &g_Config.m_PlayerColorBody; + paColors[1] = &g_Config.m_PlayerColorFeet; + + const char *paParts[] = { + Localize("Body"), + Localize("Feet")}; + const char *paLabels[] = { + Localize("Hue"), + Localize("Sat."), + Localize("Lht.")}; + static int s_aColorSlider[2][3] = {{0}}; //static float v[2][3] = {{0, 0.5f, 0.25f}, {0, 0.5f, 0.25f}}; - + for(int i = 0; i < 2; i++) { - CUIRect text; - main_view.HSplitTop(20.0f, &text, &main_view); - text.VSplitLeft(15.0f, 0, &text); - UI()->DoLabel(&text, parts[i], 14.0f, -1); - - int prevcolor = *colors[i]; - int color = 0; + CUIRect Text; + RightView.HSplitTop(20.0f, &Text, &RightView); + Text.VSplitLeft(15.0f, 0, &Text); + UI()->DoLabel(&Text, paParts[i], 14.0f, -1); + + int PrevColor = *paColors[i]; + int Color = 0; for(int s = 0; s < 3; s++) { - CUIRect text; - main_view.HSplitTop(19.0f, &button, &main_view); - button.VSplitLeft(30.0f, 0, &button); - button.VSplitLeft(70.0f, &text, &button); - button.VSplitRight(5.0f, &button, 0); - button.HSplitTop(4.0f, 0, &button); - - float k = ((prevcolor>>((2-s)*8))&0xff) / 255.0f; - k = DoScrollbarH(&color_slider[i][s], &button, k); - color <<= 8; - color += clamp((int)(k*255), 0, 255); - UI()->DoLabel(&text, labels[s], 15.0f, -1); - + CUIRect Text; + RightView.HSplitTop(19.0f, &Button, &RightView); + Button.VSplitLeft(30.0f, 0, &Button); + Button.VSplitLeft(70.0f, &Text, &Button); + Button.VSplitRight(5.0f, &Button, 0); + Button.HSplitTop(4.0f, 0, &Button); + + float k = ((PrevColor>>((2-s)*8))&0xff) / 255.0f; + k = DoScrollbarH(&s_aColorSlider[i][s], &Button, k); + Color <<= 8; + Color += clamp((int)(k*255), 0, 255); + UI()->DoLabel(&Text, paLabels[s], 15.0f, -1); + } - - if(*colors[i] != color) - need_sendinfo = true; - - *colors[i] = color; - main_view.HSplitTop(5.0f, 0, &main_view); + + if(*paColors[i] != Color) + m_NeedSendinfo = true; + + *paColors[i] = Color; + RightView.HSplitTop(5.0f, 0, &RightView); } } - + + MainView.HSplitTop(MainView.h/2, 0, &MainView); + // render skinselector - static int skinselector_id = 0; - ui_do_listbox_start(&skinselector_id, &main_view, 50, localize("Skins"), (gameclient.skins->num()+3)/4, 0); + static const int s_MaxSkins = 256; + static const CSkins::CSkin *s_paSkinList[s_MaxSkins]; + static int s_NumSkins = -1; + static float s_ScrollValue = 0; + if(s_NumSkins == -1) + { + mem_zero(s_paSkinList, sizeof(s_paSkinList)); + s_NumSkins = 0; + for(int i = 0; i < m_pClient->m_pSkins->Num() && i < s_MaxSkins; ++i) + { + const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i); + // no special skins + if(s->m_aName[0] == 'x' && s->m_aName[1] == '_') + continue; + s_paSkinList[s_NumSkins++] = s; + } + } - for(int skin_id = 0; skin_id < gameclient.skins->num(); ) + int OldSelected = -1; + UiDoListboxStart(&s_NumSkins , &MainView, 50.0f, Localize("Skins"), "", s_NumSkins, 4, OldSelected, s_ScrollValue); + + for(int i = 0; i < s_NumSkins; ++i) { - LISTBOXITEM item = ui_do_listbox_nextrow(); - CUIRect boxes[4]; - CUIRect first_half, second_half; - item.rect.VSplitMid(&first_half, &second_half); - first_half.VSplitMid(&boxes[0], &boxes[1]); - second_half.VSplitMid(&boxes[2], &boxes[3]); - - for(int i = 0; i < 4 && skin_id < gameclient.skins->num(); i++, skin_id++) + const CSkins::CSkin *s = s_paSkinList[i]; + if(s == 0) + continue; + + if(str_comp(s->m_aName, g_Config.m_PlayerSkin) == 0) + OldSelected = i; + + CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], OldSelected == i); + if(Item.m_Visible) { - //CUIRect r = item. - const SKINS::SKIN *s = gameclient.skins->get(skin_id); - - TEE_RENDER_INFO info; - info.texture = s->org_texture; - info.color_body = vec4(1,1,1,1); - info.color_feet = vec4(1,1,1,1); - if(config.player_use_custom_color) + CTeeRenderInfo Info; + Info.m_Texture = s->m_OrgTexture; + Info.m_ColorBody = vec4(1, 1, 1, 1); + Info.m_ColorFeet = vec4(1, 1, 1, 1); + + if(g_Config.m_PlayerUseCustomColor) { - info.color_body = gameclient.skins->get_color(config.player_color_body); - info.color_feet = gameclient.skins->get_color(config.player_color_feet); - info.texture = s->color_texture; + Info.m_ColorBody = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorBody); + Info.m_ColorFeet = m_pClient->m_pSkins->GetColor(g_Config.m_PlayerColorFeet); + Info.m_Texture = s->m_ColorTexture; } - - info.size = UI()->Scale()*50.0f; - - CUIRect icon = boxes[i]; //item.rect; - //button.VSplitLeft(50.0f, &icon, &text); - - /*if(UI()->DoButton(s, "", selected, &button, ui_draw_list_row, 0)) - { - config_set_player_skin(&config, s->name); - need_sendinfo = true; - }*/ - - //text.HSplitTop(12.0f, 0, &text); // some margin from the top - //UI()->DoLabel(&text, buf, 18.0f, 0); - - icon.HSplitTop(5.0f, 0, &icon); // some margin from the top - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, 0, vec2(1, 0), vec2(icon.x+icon.w/2, icon.y+icon.h/2)); - - if(config.debug) + + Info.m_Size = UI()->Scale()*50.0f; + Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top + RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1, 0), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); + + if(g_Config.m_Debug) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - Graphics()->SetColor(s->blood_color.r, s->blood_color.g, s->blood_color.b, 1.0f); - Graphics()->QuadsDrawTL(icon.x, icon.y, 12, 12); + Graphics()->SetColor(s->m_BloodColor.r, s->m_BloodColor.g, s->m_BloodColor.b, 1.0f); + IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, 12, 12); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } } } - - int new_selection = ui_do_listbox_end(); - (void)new_selection; - //main_view - } - - // render skinselector - /* - { - - //othersection - } - - // draw header - CUIRect header, footer; - skinselection.HSplitTop(20, &header, &skinselection); - RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - UI()->DoLabel(&header, localize("Skins"), 18.0f, 0); - - // draw footers - skinselection.HSplitBottom(20, &skinselection, &footer); - RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - footer.VSplitLeft(10.0f, 0, &footer); - - // modes - RenderTools()->DrawUIRect(&skinselection, vec4(0,0,0,0.15f), 0, 0); - - CUIRect scroll; - skinselection.VSplitRight(15, &skinselection, &scroll); - - CUIRect list = skinselection; - list.HSplitTop(50, &button, &list); - - int num = (int)(skinselection.h/button.h); - static float scrollvalue = 0; - static int scrollbar = 0; - scroll.HMargin(5.0f, &scroll); - scrollvalue = ui_do_scrollbar_v(&scrollbar, &scroll, scrollvalue); - - int start = (int)((gameclient.skins->num()-num)*scrollvalue); - if(start < 0) - start = 0; - - for(int i = start; i < start+num && i < gameclient.skins->num(); i++) - { - const SKINS::SKIN *s = gameclient.skins->get(i); - - // no special skins - if(s->name[0] == 'x' && s->name[1] == '_') - { - num++; - continue; - } - - char buf[128]; - str_format(buf, sizeof(buf), "%s", s->name); - int selected = 0; - if(strcmp(s->name, config.player_skin) == 0) - selected = 1; - - TEE_RENDER_INFO info; - info.texture = s->org_texture; - info.color_body = vec4(1,1,1,1); - info.color_feet = vec4(1,1,1,1); - if(config.player_use_custom_color) - { - info.color_body = gameclient.skins->get_color(config.player_color_body); - info.color_feet = gameclient.skins->get_color(config.player_color_feet); - info.texture = s->color_texture; - } - - info.size = UI()->Scale()*50.0f; - - CUIRect icon; - CUIRect text; - button.VSplitLeft(50.0f, &icon, &text); - - if(UI()->DoButton(s, "", selected, &button, ui_draw_list_row, 0)) - { - config_set_player_skin(&config, s->name); - need_sendinfo = true; - } - text.HSplitTop(12.0f, 0, &text); // some margin from the top - UI()->DoLabel(&text, buf, 18.0f, 0); - - icon.HSplitTop(5.0f, 0, &icon); // some margin from the top - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &info, 0, vec2(1, 0), vec2(icon.x+icon.w/2, icon.y+icon.h/2)); - - if(config.debug) + const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); + if(OldSelected != NewSelected) { - Graphics()->TextureSet(-1); - Graphics()->QuadsBegin(); - Graphics()->SetColor(s->blood_color.r, s->blood_color.g, s->blood_color.b, 1.0f); - Graphics()->QuadsDrawTL(icon.x, icon.y, 12, 12); - Graphics()->QuadsEnd(); + mem_copy(g_Config.m_PlayerSkin, s_paSkinList[NewSelected]->m_aName, sizeof(g_Config.m_PlayerSkin)); + m_NeedSendinfo = true; } - - list.HSplitTop(50, &button, &list); - }*/ + } } -typedef void (*assign_func_callback)(CONFIGURATION *config, int value); +typedef void (*pfnAssignFuncCallback)(CConfiguration *pConfig, int Value); -typedef struct +typedef struct { - LOC_CONSTSTRING name; - const char *command; - int keyid; -} KEYINFO; + CLocConstString m_Name; + const char *m_pCommand; + int m_KeyId; +} CKeyInfo; -static KEYINFO keys[] = +static CKeyInfo gs_aKeys[] = { // we need to do localize so the scripts can pickup the string - { localize("Move left"), "+left", 0}, - { localize("Move right"), "+right", 0 }, - { localize("Jump"), "+jump", 0 }, - { localize("Fire"), "+fire", 0 }, - { localize("Hook"), "+hook", 0 }, - { localize("Hammer"), "+weapon1", 0 }, - { localize("Pistol"), "+weapon2", 0 }, - { localize("Shotgun"), "+weapon3", 0 }, - { localize("Grenade"), "+weapon4", 0 }, - { localize("Rifle"), "+weapon5", 0 }, - { localize("Next weapon"), "+nextweapon", 0 }, - { localize("Prev. weapon"), "+prevweapon", 0 }, - { localize("Vote yes"), "vote yes", 0 }, - { localize("Vote no"), "vote no", 0 }, - { localize("Chat"), "chat all", 0 }, - { localize("Team chat"), "chat team", 0 }, - { localize("Emoticon"), "+emote", 0 }, - { localize("Console"), "toggle_local_console", 0 }, - { localize("Remote console"), "toggle_remote_console", 0 }, - { localize("Screenshot"), "screenshot", 0 }, - { localize("Scoreboard"), "+scoreboard", 0 }, + { Localize("Move left"), "+left", 0}, + { Localize("Move right"), "+right", 0 }, + { Localize("Jump"), "+jump", 0 }, + { Localize("Fire"), "+fire", 0 }, + { Localize("Hook"), "+hook", 0 }, + { Localize("Hammer"), "+weapon1", 0 }, + { Localize("Pistol"), "+weapon2", 0 }, + { Localize("Shotgun"), "+weapon3", 0 }, + { Localize("Grenade"), "+weapon4", 0 }, + { Localize("Rifle"), "+weapon5", 0 }, + { Localize("Next weapon"), "+nextweapon", 0 }, + { Localize("Prev. weapon"), "+prevweapon", 0 }, + { Localize("Vote yes"), "vote yes", 0 }, + { Localize("Vote no"), "vote no", 0 }, + { Localize("Chat"), "chat all", 0 }, + { Localize("Team chat"), "chat team", 0 }, + { Localize("Emoticon"), "+emote", 0 }, + { Localize("Console"), "toggle_local_console", 0 }, + { Localize("Remote console"), "toggle_remote_console", 0 }, + { Localize("Screenshot"), "screenshot", 0 }, + { Localize("Scoreboard"), "+scoreboard", 0 }, }; -const int key_count = sizeof(keys) / sizeof(KEYINFO); +const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); -void MENUS::ui_do_getbuttons(int start, int stop, CUIRect view) +void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View) { - for (int i = start; i < stop; i++) + for (int i = Start; i < Stop; i++) { - KEYINFO &key = keys[i]; - CUIRect button, label; - view.HSplitTop(20.0f, &button, &view); - button.VSplitLeft(130.0f, &label, &button); - - char buf[64]; - str_format(buf, sizeof(buf), "%s:", (const char *)key.name); - - UI()->DoLabel(&label, key.name, 14.0f, -1); - int oldid = key.keyid; - int newid = DoKeyReader((void *)&keys[i].name, &button, oldid); - if(newid != oldid) + CKeyInfo &Key = gs_aKeys[i]; + CUIRect Button, Label; + View.HSplitTop(20.0f, &Button, &View); + Button.VSplitLeft(130.0f, &Label, &Button); + + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s:", (const char *)Key.m_Name); + + UI()->DoLabel(&Label, aBuf, 14.0f, -1); + int OldId = Key.m_KeyId; + int NewId = DoKeyReader((void *)&gs_aKeys[i].m_Name, &Button, OldId); + if(NewId != OldId) { - gameclient.binds->bind(oldid, ""); - gameclient.binds->bind(newid, keys[i].command); + m_pClient->m_pBinds->Bind(OldId, ""); + m_pClient->m_pBinds->Bind(NewId, gs_aKeys[i].m_pCommand); } - view.HSplitTop(5.0f, 0, &view); + View.HSplitTop(5.0f, 0, &View); } } -void MENUS::render_settings_controls(CUIRect main_view) +void CMenus::RenderSettingsControls(CUIRect MainView) { // this is kinda slow, but whatever - for(int i = 0; i < key_count; i++) - keys[i].keyid = 0; - - for(int keyid = 0; keyid < KEY_LAST; keyid++) + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) { - const char *bind = gameclient.binds->get(keyid); - if(!bind[0]) + const char *pBind = m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) continue; - - for(int i = 0; i < key_count; i++) - if(strcmp(bind, keys[i].command) == 0) + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) { - keys[i].keyid = keyid; + gs_aKeys[i].m_KeyId = KeyId; break; } } - CUIRect movement_settings, weapon_settings, voting_settings, chat_settings, misc_settings, reset_button; - main_view.VSplitLeft(main_view.w/2-5.0f, &movement_settings, &voting_settings); - - /* movement settings */ + CUIRect MovementSettings, WeaponSettings, VotingSettings, ChatSettings, MiscSettings, ResetButton; + MainView.VSplitLeft(MainView.w/2-5.0f, &MovementSettings, &VotingSettings); + + // movement settings { - movement_settings.HSplitTop(main_view.h/2-5.0f, &movement_settings, &weapon_settings); - RenderTools()->DrawUIRect(&movement_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - movement_settings.Margin(10.0f, &movement_settings); - - gfx_text(0, movement_settings.x, movement_settings.y, 14, localize("Movement"), -1); - - movement_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &movement_settings); - + MovementSettings.HSplitTop(MainView.h/2-5.0f, &MovementSettings, &WeaponSettings); + RenderTools()->DrawUIRect(&MovementSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + MovementSettings.Margin(10.0f, &MovementSettings); + + TextRender()->Text(0, MovementSettings.x, MovementSettings.y, 14, Localize("Movement"), -1); + + MovementSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MovementSettings); + { - CUIRect button, label; - movement_settings.HSplitTop(20.0f, &button, &movement_settings); - button.VSplitLeft(130.0f, &label, &button); - UI()->DoLabel(&label, localize("Mouse sens."), 14.0f, -1); - button.HMargin(2.0f, &button); - config.inp_mousesens = (int)(DoScrollbarV(&config.inp_mousesens, &button, (config.inp_mousesens-5)/500.0f)*500.0f)+5; - //*key.key = ui_do_key_reader(key.key, &button, *key.key); - movement_settings.HSplitTop(20.0f, 0, &movement_settings); + CUIRect Button, Label; + MovementSettings.HSplitTop(20.0f, &Button, &MovementSettings); + Button.VSplitLeft(130.0f, &Label, &Button); + UI()->DoLabel(&Label, Localize("Mouse sens."), 14.0f, -1); + Button.HMargin(2.0f, &Button); + g_Config.m_InpMousesens = (int)(DoScrollbarH(&g_Config.m_InpMousesens, &Button, (g_Config.m_InpMousesens-5)/500.0f)*500.0f)+5; + //*key.key = ui_do_key_reader(key.key, &Button, *key.key); + MovementSettings.HSplitTop(20.0f, 0, &MovementSettings); } - - ui_do_getbuttons(0, 5, movement_settings); + + UiDoGetButtons(0, 5, MovementSettings); } - - /* weapon settings */ + + // weapon settings { - weapon_settings.HSplitTop(10.0f, 0, &weapon_settings); - RenderTools()->DrawUIRect(&weapon_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - weapon_settings.Margin(10.0f, &weapon_settings); - - gfx_text(0, weapon_settings.x, weapon_settings.y, 14, localize("Weapon"), -1); - - weapon_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &weapon_settings); - ui_do_getbuttons(5, 12, weapon_settings); + WeaponSettings.HSplitTop(10.0f, 0, &WeaponSettings); + RenderTools()->DrawUIRect(&WeaponSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + WeaponSettings.Margin(10.0f, &WeaponSettings); + + TextRender()->Text(0, WeaponSettings.x, WeaponSettings.y, 14, Localize("Weapon"), -1); + + WeaponSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &WeaponSettings); + UiDoGetButtons(5, 12, WeaponSettings); } - - /* voting settings */ + + // voting settings { - voting_settings.VSplitLeft(10.0f, 0, &voting_settings); - voting_settings.HSplitTop(main_view.h/4-5.0f, &voting_settings, &chat_settings); - RenderTools()->DrawUIRect(&voting_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - voting_settings.Margin(10.0f, &voting_settings); - - gfx_text(0, voting_settings.x, voting_settings.y, 14, localize("Voting"), -1); - - voting_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &voting_settings); - ui_do_getbuttons(12, 14, voting_settings); + VotingSettings.VSplitLeft(10.0f, 0, &VotingSettings); + VotingSettings.HSplitTop(MainView.h/4-5.0f, &VotingSettings, &ChatSettings); + RenderTools()->DrawUIRect(&VotingSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + VotingSettings.Margin(10.0f, &VotingSettings); + + TextRender()->Text(0, VotingSettings.x, VotingSettings.y, 14, Localize("Voting"), -1); + + VotingSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &VotingSettings); + UiDoGetButtons(12, 14, VotingSettings); } - - /* chat settings */ + + // chat settings { - chat_settings.HSplitTop(10.0f, 0, &chat_settings); - chat_settings.HSplitTop(main_view.h/4-10.0f, &chat_settings, &misc_settings); - RenderTools()->DrawUIRect(&chat_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - chat_settings.Margin(10.0f, &chat_settings); - - gfx_text(0, chat_settings.x, chat_settings.y, 14, localize("Chat"), -1); - - chat_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &chat_settings); - ui_do_getbuttons(14, 16, chat_settings); + ChatSettings.HSplitTop(10.0f, 0, &ChatSettings); + ChatSettings.HSplitTop(MainView.h/4-10.0f, &ChatSettings, &MiscSettings); + RenderTools()->DrawUIRect(&ChatSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + ChatSettings.Margin(10.0f, &ChatSettings); + + TextRender()->Text(0, ChatSettings.x, ChatSettings.y, 14, Localize("Chat"), -1); + + ChatSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &ChatSettings); + UiDoGetButtons(14, 16, ChatSettings); } - - /* misc settings */ + + // misc settings { - misc_settings.HSplitTop(10.0f, 0, &misc_settings); - misc_settings.HSplitTop(main_view.h/2-5.0f-45.0f, &misc_settings, &reset_button); - RenderTools()->DrawUIRect(&misc_settings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - misc_settings.Margin(10.0f, &misc_settings); - - gfx_text(0, misc_settings.x, misc_settings.y, 14, localize("Miscellaneous"), -1); - - misc_settings.HSplitTop(14.0f+5.0f+10.0f, 0, &misc_settings); - ui_do_getbuttons(16, 21, misc_settings); + MiscSettings.HSplitTop(10.0f, 0, &MiscSettings); + MiscSettings.HSplitTop(MainView.h/2-5.0f-45.0f, &MiscSettings, &ResetButton); + RenderTools()->DrawUIRect(&MiscSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + MiscSettings.Margin(10.0f, &MiscSettings); + + TextRender()->Text(0, MiscSettings.x, MiscSettings.y, 14, Localize("Miscellaneous"), -1); + + MiscSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MiscSettings); + UiDoGetButtons(16, 21, MiscSettings); } - + // defaults - reset_button.HSplitTop(10.0f, 0, &reset_button); - static int default_button = 0; - if(DoButton_Menu((void*)&default_button, localize("Reset to defaults"), 0, &reset_button)) - gameclient.binds->set_defaults(); + ResetButton.HSplitTop(10.0f, 0, &ResetButton); + static int s_DefaultButton = 0; + if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) + m_pClient->m_pBinds->SetDefaults(); } -void MENUS::render_settings_graphics(CUIRect main_view) +void CMenus::RenderSettingsGraphics(CUIRect MainView) { - CUIRect button; - char buf[128]; - + CUIRect Button; + char aBuf[128]; + static const int MAX_RESOLUTIONS = 256; - static VIDEO_MODE modes[MAX_RESOLUTIONS]; - static int num_modes = -1; - - if(num_modes == -1) - num_modes = gfx_get_video_modes(modes, MAX_RESOLUTIONS); - - CUIRect modelist; - main_view.VSplitLeft(300.0f, &main_view, &modelist); - + static CVideoMode s_aModes[MAX_RESOLUTIONS]; + static int s_NumNodes = -1; + const static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth; + const static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight; + const static int s_GfxColorDepth = g_Config.m_GfxColorDepth; + + if(s_NumNodes == -1) + s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS); + + CUIRect ModeList; + MainView.VSplitLeft(300.0f, &MainView, &ModeList); + // draw allmodes switch - CUIRect header, footer; - modelist.HSplitTop(20, &button, &modelist); - if(DoButton_CheckBox(&config.gfx_display_all_modes, localize("Show only supported"), config.gfx_display_all_modes^1, &button)) + ModeList.HSplitTop(20, &Button, &ModeList); + if(DoButton_CheckBox(&g_Config.m_GfxDisplayAllModes, Localize("Show only supported"), g_Config.m_GfxDisplayAllModes^1, &Button)) { - config.gfx_display_all_modes ^= 1; - num_modes = gfx_get_video_modes(modes, MAX_RESOLUTIONS); + g_Config.m_GfxDisplayAllModes ^= 1; + s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS); } - - // draw header - modelist.HSplitTop(20, &header, &modelist); - RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - UI()->DoLabel(&header, localize("Display Modes"), 14.0f, 0); - - // draw footers - modelist.HSplitBottom(20, &modelist, &footer); - str_format(buf, sizeof(buf), "%s: %dx%d %d bit", localize("Current"), config.gfx_screen_width, config.gfx_screen_height, config.gfx_color_depth); - RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - footer.VSplitLeft(10.0f, 0, &footer); - UI()->DoLabel(&footer, buf, 14.0f, -1); - - // modes - RenderTools()->DrawUIRect(&modelist, vec4(0,0,0,0.15f), 0, 0); - - CUIRect scroll; - modelist.VSplitRight(15, &modelist, &scroll); - - CUIRect list = modelist; - list.HSplitTop(20, &button, &list); - - int num = (int)(modelist.h/button.h); - static float scrollvalue = 0; - static int scrollbar = 0; - scroll.HMargin(5.0f, &scroll); - scrollvalue = DoScrollbarV(&scrollbar, &scroll, scrollvalue); - - int start = (int)((num_modes-num)*scrollvalue); - if(start < 0) - start = 0; - - for(int i = start; i < start+num && i < num_modes; i++) + + // display mode list + static float s_ScrollValue = 0; + int OldSelected = -1; + str_format(aBuf, sizeof(aBuf), "%s: %dx%d %d bit", Localize("Current"), s_GfxScreenWidth, s_GfxScreenHeight, s_GfxColorDepth); + UiDoListboxStart(&s_NumNodes , &ModeList, 24.0f, Localize("Display Modes"), aBuf, s_NumNodes, 1, OldSelected, s_ScrollValue); + + for(int i = 0; i < s_NumNodes; ++i) { - int depth = modes[i].red+modes[i].green+modes[i].blue; - if(depth < 16) - depth = 16; - else if(depth > 16) - depth = 24; - - int selected = 0; - if(config.gfx_color_depth == depth && - config.gfx_screen_width == modes[i].width && - config.gfx_screen_height == modes[i].height) + const int Depth = s_aModes[i].m_Red+s_aModes[i].m_Green+s_aModes[i].m_Blue > 16 ? 24 : 16; + if(g_Config.m_GfxColorDepth == Depth && + g_Config.m_GfxScreenWidth == s_aModes[i].m_Width && + g_Config.m_GfxScreenHeight == s_aModes[i].m_Height) { - selected = 1; + OldSelected = i; } - - str_format(buf, sizeof(buf), " %dx%d %d bit", modes[i].width, modes[i].height, depth); - if(DoButton_ListRow(&modes[i], buf, selected, &button)) + + CListboxItem Item = UiDoListboxNextItem(&s_aModes[i], OldSelected == i); + if(Item.m_Visible) { - config.gfx_color_depth = depth; - config.gfx_screen_width = modes[i].width; - config.gfx_screen_height = modes[i].height; - if(!selected) - need_restart = true; + str_format(aBuf, sizeof(aBuf), " %dx%d %d bit", s_aModes[i].m_Width, s_aModes[i].m_Height, Depth); + UI()->DoLabel(&Item.m_Rect, aBuf, 16.0f, -1); } - - list.HSplitTop(20, &button, &list); } - - + + const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); + if(OldSelected != NewSelected) + { + const int Depth = s_aModes[NewSelected].m_Red+s_aModes[NewSelected].m_Green+s_aModes[NewSelected].m_Blue > 16 ? 24 : 16; + g_Config.m_GfxColorDepth = Depth; + g_Config.m_GfxScreenWidth = s_aModes[NewSelected].m_Width; + g_Config.m_GfxScreenHeight = s_aModes[NewSelected].m_Height; + m_NeedRestart = true; + } + // switches - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.gfx_fullscreen, localize("Fullscreen"), config.gfx_fullscreen, &button)) + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button)) { - config.gfx_fullscreen ^= 1; - need_restart = true; + g_Config.m_GfxFullscreen ^= 1; + m_NeedRestart = true; } - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.gfx_vsync, localize("V-Sync"), config.gfx_vsync, &button)) + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button)) { - config.gfx_vsync ^= 1; - need_restart = true; + g_Config.m_GfxVsync ^= 1; + m_NeedRestart = true; } - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox_Number(&config.gfx_fsaa_samples, localize("FSAA samples"), config.gfx_fsaa_samples, &button)) + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox_Number(&g_Config.m_GfxFsaaSamples, Localize("FSAA samples"), g_Config.m_GfxFsaaSamples, &Button)) { - config.gfx_fsaa_samples = (config.gfx_fsaa_samples+1)%17; - need_restart = true; + g_Config.m_GfxFsaaSamples = (g_Config.m_GfxFsaaSamples+1)%17; + m_NeedRestart = true; } - - main_view.HSplitTop(40.0f, &button, &main_view); - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.gfx_texture_quality, localize("Quality Textures"), config.gfx_texture_quality, &button)) + + MainView.HSplitTop(40.0f, &Button, &MainView); + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button)) { - config.gfx_texture_quality ^= 1; - need_restart = true; + g_Config.m_GfxTextureQuality ^= 1; + m_NeedRestart = true; } - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.gfx_texture_compression, localize("Texture Compression"), config.gfx_texture_compression, &button)) + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxTextureCompression, Localize("Texture Compression"), g_Config.m_GfxTextureCompression, &Button)) { - config.gfx_texture_compression ^= 1; - need_restart = true; + g_Config.m_GfxTextureCompression ^= 1; + m_NeedRestart = true; } - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.gfx_high_detail, localize("High Detail"), config.gfx_high_detail, &button)) - config.gfx_high_detail ^= 1; + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button)) + g_Config.m_GfxHighDetail ^= 1; // - - CUIRect text; - main_view.HSplitTop(20.0f, 0, &main_view); - main_view.HSplitTop(20.0f, &text, &main_view); + + CUIRect Text; + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(20.0f, &Text, &MainView); //text.VSplitLeft(15.0f, 0, &text); - UI()->DoLabel(&text, localize("UI Color"), 14.0f, -1); - - const char *labels[] = { - localize("Hue"), - localize("Sat."), - localize("Lht."), - localize("Alpha")}; - int *color_slider[4] = {&config.ui_color_hue, &config.ui_color_sat, &config.ui_color_lht, &config.ui_color_alpha}; + UI()->DoLabel(&Text, Localize("UI Color"), 14.0f, -1); + + const char *paLabels[] = { + Localize("Hue"), + Localize("Sat."), + Localize("Lht."), + Localize("Alpha")}; + int *pColorSlider[4] = {&g_Config.m_UiColorHue, &g_Config.m_UiColorSat, &g_Config.m_UiColorLht, &g_Config.m_UiColorAlpha}; for(int s = 0; s < 4; s++) { - CUIRect text; - main_view.HSplitTop(19.0f, &button, &main_view); - button.VMargin(15.0f, &button); - button.VSplitLeft(50.0f, &text, &button); - button.VSplitRight(5.0f, &button, 0); - button.HSplitTop(4.0f, 0, &button); - - float k = (*color_slider[s]) / 255.0f; - k = DoScrollbarH(color_slider[s], &button, k); - *color_slider[s] = (int)(k*255.0f); - UI()->DoLabel(&text, labels[s], 15.0f, -1); - } + CUIRect Text; + MainView.HSplitTop(19.0f, &Button, &MainView); + Button.VMargin(15.0f, &Button); + Button.VSplitLeft(50.0f, &Text, &Button); + Button.VSplitRight(5.0f, &Button, 0); + Button.HSplitTop(4.0f, 0, &Button); + + float k = (*pColorSlider[s]) / 255.0f; + k = DoScrollbarH(pColorSlider[s], &Button, k); + *pColorSlider[s] = (int)(k*255.0f); + UI()->DoLabel(&Text, paLabels[s], 15.0f, -1); + } } -void MENUS::render_settings_sound(CUIRect main_view) +void CMenus::RenderSettingsSound(CUIRect MainView) { - CUIRect button; - main_view.VSplitLeft(300.0f, &main_view, 0); - - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.snd_enable, localize("Use sounds"), config.snd_enable, &button)) + CUIRect Button; + MainView.VSplitLeft(300.0f, &MainView, 0); + + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_SndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button)) { - config.snd_enable ^= 1; - need_restart = true; + g_Config.m_SndEnable ^= 1; + m_NeedRestart = true; } - - if(!config.snd_enable) + + if(!g_Config.m_SndEnable) return; - - main_view.HSplitTop(20.0f, &button, &main_view); - if(DoButton_CheckBox(&config.snd_nonactive_mute, localize("Mute when not active"), config.snd_nonactive_mute, &button)) - config.snd_nonactive_mute ^= 1; - + + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_SndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button)) + g_Config.m_SndNonactiveMute ^= 1; + // sample rate box { - char buf[64]; - str_format(buf, sizeof(buf), "%d", config.snd_rate); - main_view.HSplitTop(20.0f, &button, &main_view); - UI()->DoLabel(&button, localize("Sample rate"), 14.0f, -1); - button.VSplitLeft(110.0f, 0, &button); - button.VSplitLeft(180.0f, &button, 0); - DoEditBox(&config.snd_rate, &button, buf, sizeof(buf), 14.0f); - int before = config.snd_rate; - config.snd_rate = atoi(buf); - - if(config.snd_rate != before) - need_restart = true; - - if(config.snd_rate < 1) - config.snd_rate = 1; + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_SndRate); + MainView.HSplitTop(20.0f, &Button, &MainView); + UI()->DoLabel(&Button, Localize("Sample rate"), 14.0f, -1); + Button.VSplitLeft(110.0f, 0, &Button); + Button.VSplitLeft(180.0f, &Button, 0); + DoEditBox(&g_Config.m_SndRate, &Button, aBuf, sizeof(aBuf), 14.0f); + int Before = g_Config.m_SndRate; + g_Config.m_SndRate = str_toint(aBuf); + + if(g_Config.m_SndRate != Before) + m_NeedRestart = true; + + if(g_Config.m_SndRate < 1) + g_Config.m_SndRate = 1; } - + // volume slider { - CUIRect button, label; - main_view.HSplitTop(5.0f, &button, &main_view); - main_view.HSplitTop(20.0f, &button, &main_view); - button.VSplitLeft(110.0f, &label, &button); - button.HMargin(2.0f, &button); - UI()->DoLabel(&label, localize("Sound volume"), 14.0f, -1); - config.snd_volume = (int)(DoScrollbarH(&config.snd_volume, &button, config.snd_volume/100.0f)*100.0f); - main_view.HSplitTop(20.0f, 0, &main_view); + CUIRect Button, Label; + MainView.HSplitTop(5.0f, &Button, &MainView); + MainView.HSplitTop(20.0f, &Button, &MainView); + Button.VSplitLeft(110.0f, &Label, &Button); + Button.HMargin(2.0f, &Button); + UI()->DoLabel(&Label, Localize("Sound volume"), 14.0f, -1); + g_Config.m_SndVolume = (int)(DoScrollbarH(&g_Config.m_SndVolume, &Button, g_Config.m_SndVolume/100.0f)*100.0f); + MainView.HSplitTop(20.0f, 0, &MainView); } } struct LANGUAGE { LANGUAGE() {} - LANGUAGE(const char *n, const char *f) : name(n), filename(f) {} - - string name; - string filename; - - bool operator<(const LANGUAGE &other) { return name < other.name; } + LANGUAGE(const char *n, const char *f) : m_Name(n), m_FileName(f) {} + + string m_Name; + string m_FileName; + + bool operator<(const LANGUAGE &Other) { return m_Name < Other.m_Name; } }; -int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, void *user); +int fs_listdir(const char *pDir, FS_LISTDIR_CALLBACK cb, void *pUser); -void gather_languages(const char *name, int is_dir, void *user) +void GatherLanguages(const char *pName, int IsDir, void *pUser) { - if(is_dir || name[0] == '.') + if(IsDir || pName[0] == '.') return; - - sorted_array<LANGUAGE> &languages = *((sorted_array<LANGUAGE> *)user); - char filename[128]; - str_format(filename, sizeof(filename), "data/languages/%s", name); - - char nicename[128]; - str_format(nicename, sizeof(nicename), "%s", name); - nicename[0] = str_uppercase(nicename[0]); - - - for(char *p = nicename; *p; p++) + + sorted_array<LANGUAGE> &Languages = *((sorted_array<LANGUAGE> *)pUser); + char aFileName[128]; + str_format(aFileName, sizeof(aFileName), "data/languages/%s", pName); + + char NiceName[128]; + str_format(NiceName, sizeof(NiceName), "%s", pName); + NiceName[0] = str_uppercase(NiceName[0]); + + + for(char *p = NiceName; *p; p++) if(*p == '.') *p = 0; - - languages.add(LANGUAGE(nicename, filename)); + + Languages.add(LANGUAGE(NiceName, aFileName)); } -void MENUS::render_settings_general(CUIRect main_view) +void CMenus::RenderSettingsGeneral(CUIRect MainView) { - static int lanuagelist = 0; - static int selected_language = 0; - static sorted_array<LANGUAGE> languages; - - if(languages.size() == 0) + static int s_LanguageList = 0; + static int s_SelectedLanguage = 0; + static sorted_array<LANGUAGE> s_Languages; + static float s_ScrollValue = 0; + + if(s_Languages.size() == 0) { - languages.add(LANGUAGE("English", "")); - fs_listdir("data/languages", gather_languages, &languages); - for(int i = 0; i < languages.size(); i++) - if(str_comp(languages[i].filename, config.cl_languagefile) == 0) + s_Languages.add(LANGUAGE("English", "")); + fs_listdir("data/languages", GatherLanguages, &s_Languages); + for(int i = 0; i < s_Languages.size(); i++) + if(str_comp(s_Languages[i].m_FileName, g_Config.m_ClLanguagefile) == 0) { - selected_language = i; + s_SelectedLanguage = i; break; } } - - int old_selected = selected_language; - - CUIRect list = main_view; - ui_do_listbox_start(&lanuagelist, &list, 24.0f, localize("Language"), languages.size(), selected_language); - - for(sorted_array<LANGUAGE>::range r = languages.all(); !r.empty(); r.pop_front()) + + int OldSelected = s_SelectedLanguage; + + CUIRect List = MainView; + UiDoListboxStart(&s_LanguageList , &List, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); + + for(sorted_array<LANGUAGE>::range r = s_Languages.all(); !r.empty(); r.pop_front()) { - LISTBOXITEM item = ui_do_listbox_nextitem(&r.front()); - - if(item.visible) - UI()->DoLabel(&item.rect, r.front().name, 16.0f, -1); + CListboxItem Item = UiDoListboxNextItem(&r.front()); + + if(Item.m_Visible) + UI()->DoLabel(&Item.m_Rect, r.front().m_Name, 16.0f, -1); } - - selected_language = ui_do_listbox_end(); - - if(old_selected != selected_language) + + s_SelectedLanguage = UiDoListboxEnd(&s_ScrollValue, 0); + + if(OldSelected != s_SelectedLanguage) { - str_copy(config.cl_languagefile, languages[selected_language].filename, sizeof(config.cl_languagefile)); - localization.load(languages[selected_language].filename); + str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile)); + g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName); } } -void MENUS::render_settings(CUIRect main_view) +void CMenus::RenderSettings(CUIRect MainView) { - static int settings_page = 0; - + static int s_SettingsPage = 0; + // render background - CUIRect temp, tabbar; - main_view.VSplitRight(120.0f, &main_view, &tabbar); - RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); - tabbar.HSplitTop(50.0f, &temp, &tabbar); - RenderTools()->DrawUIRect(&temp, color_tabbar_active, CUI::CORNER_R, 10.0f); - - main_view.HSplitTop(10.0f, 0, &main_view); - - CUIRect button; - - const char *tabs[] = { - localize("General"), - localize("Player"), - localize("Controls"), - localize("Graphics"), - localize("Sound")}; - - int num_tabs = (int)(sizeof(tabs)/sizeof(*tabs)); - - for(int i = 0; i < num_tabs; i++) + CUIRect Temp, TabBar; + MainView.VSplitRight(120.0f, &MainView, &TabBar); + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B|CUI::CORNER_TL, 10.0f); + TabBar.HSplitTop(50.0f, &Temp, &TabBar); + RenderTools()->DrawUIRect(&Temp, ms_ColorTabbarActive, CUI::CORNER_R, 10.0f); + + MainView.HSplitTop(10.0f, 0, &MainView); + + CUIRect Button; + + const char *aTabs[] = { + Localize("General"), + Localize("Player"), + Localize("Controls"), + Localize("Graphics"), + Localize("Sound")}; + + int NumTabs = (int)(sizeof(aTabs)/sizeof(*aTabs)); + + for(int i = 0; i < NumTabs; i++) { - tabbar.HSplitTop(10, &button, &tabbar); - tabbar.HSplitTop(26, &button, &tabbar); - if(DoButton_SettingsTab(tabs[i], tabs[i], settings_page == i, &button)) - settings_page = i; + TabBar.HSplitTop(10, &Button, &TabBar); + TabBar.HSplitTop(26, &Button, &TabBar); + if(DoButton_SettingsTab(aTabs[i], aTabs[i], s_SettingsPage == i, &Button)) + s_SettingsPage = i; } - - main_view.Margin(10.0f, &main_view); - - if(settings_page == 0) - render_settings_general(main_view); - else if(settings_page == 1) - render_settings_player(main_view); - else if(settings_page == 2) - render_settings_controls(main_view); - else if(settings_page == 3) - render_settings_graphics(main_view); - else if(settings_page == 4) - render_settings_sound(main_view); - - if(need_restart) + + MainView.Margin(10.0f, &MainView); + + if(s_SettingsPage == 0) + RenderSettingsGeneral(MainView); + else if(s_SettingsPage == 1) + RenderSettingsPlayer(MainView); + else if(s_SettingsPage == 2) + RenderSettingsControls(MainView); + else if(s_SettingsPage == 3) + RenderSettingsGraphics(MainView); + else if(s_SettingsPage == 4) + RenderSettingsSound(MainView); + + if(m_NeedRestart) { - CUIRect restart_warning; - main_view.HSplitBottom(40, &main_view, &restart_warning); - UI()->DoLabel(&restart_warning, localize("You must restart the game for all settings to take effect."), 15.0f, -1, 220); + CUIRect RestartWarning; + MainView.HSplitBottom(40, &MainView, &RestartWarning); + UI()->DoLabel(&RestartWarning, Localize("You must restart the game for all settings to take effect."), 15.0f, -1, 220); } } diff --git a/src/game/client/components/motd.cpp b/src/game/client/components/motd.cpp index ba85f7f8..5905d52e 100644 --- a/src/game/client/components/motd.cpp +++ b/src/game/client/components/motd.cpp @@ -1,87 +1,91 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <engine/e_config.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/keys.h> -#include <game/client/gameclient.hpp> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> +#include <game/client/gameclient.h> -#include "motd.hpp" +#include "motd.h" -void MOTD::clear() +void CMotd::Clear() { - server_motd_time = 0; + m_ServerMotdTime = 0; } -bool MOTD::is_active() +bool CMotd::IsActive() { - return time_get() < server_motd_time; + return time_get() < m_ServerMotdTime; } -void MOTD::on_statechange(int new_state, int old_state) +void CMotd::OnStateChange(int NewState, int OldState) { - if(old_state == CLIENTSTATE_ONLINE || old_state == CLIENTSTATE_OFFLINE) - clear(); + if(OldState == IClient::STATE_ONLINE || OldState == IClient::STATE_OFFLINE) + Clear(); } -void MOTD::on_render() +void CMotd::OnRender() { - if(!is_active()) + if(!IsActive()) return; - float width = 400*3.0f*Graphics()->ScreenAspect(); - float height = 400*3.0f; + float Width = 400*3.0f*Graphics()->ScreenAspect(); + float Height = 400*3.0f; - Graphics()->MapScreen(0, 0, width, height); + Graphics()->MapScreen(0, 0, Width, Height); float h = 800.0f; float w = 650.0f; - float x = width/2 - w/2; + float x = Width/2 - w/2; float y = 150.0f; Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->draw_round_rect(x, y, w, h, 40.0f); + RenderTools()->DrawRoundRect(x, y, w, h, 40.0f); Graphics()->QuadsEnd(); - gfx_text(0, x+40.0f, y+40.0f, 32.0f, server_motd, (int)(w-80.0f)); + TextRender()->Text(0, x+40.0f, y+40.0f, 32.0f, m_aServerMotd, (int)(w-80.0f)); } -void MOTD::on_message(int msgtype, void *rawmsg) +void CMotd::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_MOTD) + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + return; + + if(MsgType == NETMSGTYPE_SV_MOTD) { - NETMSG_SV_MOTD *msg = (NETMSG_SV_MOTD *)rawmsg; + CNetMsg_Sv_Motd *pMsg = (CNetMsg_Sv_Motd *)pRawMsg; // process escaping - str_copy(server_motd, msg->message, sizeof(server_motd)); - for(int i = 0; server_motd[i]; i++) + str_copy(m_aServerMotd, pMsg->m_pMessage, sizeof(m_aServerMotd)); + for(int i = 0; m_aServerMotd[i]; i++) { - if(server_motd[i] == '\\') + if(m_aServerMotd[i] == '\\') { - if(server_motd[i+1] == 'n') + if(m_aServerMotd[i+1] == 'n') { - server_motd[i] = ' '; - server_motd[i+1] = '\n'; + m_aServerMotd[i] = ' '; + m_aServerMotd[i+1] = '\n'; i++; } } } - if(server_motd[0] && config.cl_motd_time) - server_motd_time = time_get()+time_freq()*config.cl_motd_time; + if(m_aServerMotd[0] && g_Config.m_ClMotdTime) + m_ServerMotdTime = time_get()+time_freq()*g_Config.m_ClMotdTime; else - server_motd_time = 0; + m_ServerMotdTime = 0; } } -bool MOTD::on_input(INPUT_EVENT e) +bool CMotd::OnInput(IInput::CEvent Event) { - if(is_active() && e.flags&INPFLAG_PRESS && e.key == KEY_ESCAPE) + if(IsActive() && Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) { - clear(); + Clear(); return true; } return false; diff --git a/src/game/client/components/motd.h b/src/game/client/components/motd.h new file mode 100644 index 00000000..41e15b8c --- /dev/null +++ b/src/game/client/components/motd.h @@ -0,0 +1,21 @@ +#ifndef GAME_CLIENT_COMPONENTS_MOTD_H +#define GAME_CLIENT_COMPONENTS_MOTD_H +#include <game/client/component.h> + +class CMotd : public CComponent +{ + // motd + int64 m_ServerMotdTime; +public: + char m_aServerMotd[900]; + + void Clear(); + bool IsActive(); + + virtual void OnRender(); + virtual void OnStateChange(int NewState, int OldState); + virtual void OnMessage(int MsgType, void *pRawMsg); + virtual bool OnInput(IInput::CEvent Event); +}; + +#endif diff --git a/src/game/client/components/motd.hpp b/src/game/client/components/motd.hpp deleted file mode 100644 index 3b175e0a..00000000 --- a/src/game/client/components/motd.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#include <game/client/component.hpp> - -class MOTD : public COMPONENT -{ - // motd - int64 server_motd_time; -public: - char server_motd[900]; - - void clear(); - bool is_active(); - - virtual void on_render(); - virtual void on_statechange(int new_state, int old_state); - virtual void on_message(int msgtype, void *rawmsg); - virtual bool on_input(INPUT_EVENT e); -}; - diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 4a47ea37..da114bbb 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -1,65 +1,66 @@ -#include <engine/e_client_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> +#include <engine/textrender.h> +#include <engine/shared/config.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include "nameplates.hpp" -#include "controls.hpp" +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include "nameplates.h" +#include "controls.h" -void NAMEPLATES::render_nameplate( - const NETOBJ_CHARACTER *prev_char, - const NETOBJ_CHARACTER *player_char, - const NETOBJ_PLAYER_INFO *player_info +void CNamePlates::RenderNameplate( + const CNetObj_Character *pPrevChar, + const CNetObj_Character *pPlayerChar, + const CNetObj_PlayerInfo *pPlayerInfo ) { - float intratick = client_intratick(); + float IntraTick = Client()->IntraGameTick(); - vec2 position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), intratick); + vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick); // render name plate - if(!player_info->local) + if(!pPlayerInfo->m_Local) { - //gfx_text_color + //TextRender()->TextColor float a = 1; - if(config.cl_nameplates_always == 0) - a = clamp(1-powf(distance(gameclient.controls->target_pos, position)/200.0f,16.0f), 0.0f, 1.0f); + if(g_Config.m_ClNameplatesAlways == 0) + a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); - const char *name = gameclient.clients[player_info->cid].name; - float tw = gfx_text_width(0, 28.0f, name, -1); - gfx_text_color(1,1,1,a); - gfx_text(0, position.x-tw/2.0f, position.y-60, 28.0f, name, -1); + const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientId].m_aName; + float tw = TextRender()->TextWidth(0, 28.0f, pName, -1); + TextRender()->TextColor(1,1,1,a); + TextRender()->Text(0, Position.x-tw/2.0f, Position.y-60, 28.0f, pName, -1); - if(config.debug) // render client id when in debug aswell + if(g_Config.m_Debug) // render client id when in debug aswell { - char buf[128]; - str_format(buf, sizeof(buf),"%d", player_info->cid); - gfx_text(0, position.x, position.y-90, 28.0f, buf, -1); + char aBuf[128]; + str_format(aBuf, sizeof(aBuf),"%d", pPlayerInfo->m_ClientId); + TextRender()->Text(0, Position.x, Position.y-90, 28.0f, aBuf, -1); } - gfx_text_color(1,1,1,1); + TextRender()->TextColor(1,1,1,1); } } -void NAMEPLATES::on_render() +void CNamePlates::OnRender() { - if (!config.cl_nameplates) + if (!g_Config.m_ClNameplates) return; for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters - if(!gameclient.snap.characters[i].active) + if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; - const void *info = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_INFO, i); + const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); - if(info) + if(pInfo) { - render_nameplate( - &gameclient.snap.characters[i].prev, - &gameclient.snap.characters[i].cur, - (const NETOBJ_PLAYER_INFO *)info); + RenderNameplate( + &m_pClient->m_Snap.m_aCharacters[i].m_Prev, + &m_pClient->m_Snap.m_aCharacters[i].m_Cur, + (const CNetObj_PlayerInfo *)pInfo); } } } diff --git a/src/game/client/components/nameplates.h b/src/game/client/components/nameplates.h new file mode 100644 index 00000000..279b6582 --- /dev/null +++ b/src/game/client/components/nameplates.h @@ -0,0 +1,17 @@ +#ifndef GAME_CLIENT_COMPONENTS_NAMEPLATES_H +#define GAME_CLIENT_COMPONENTS_NAMEPLATES_H +#include <game/client/component.h> + +class CNamePlates : public CComponent +{ + void RenderNameplate( + const class CNetObj_Character *pPrevChar, + const class CNetObj_Character *pPlayerChar, + const class CNetObj_PlayerInfo *pPlayerInfo + ); + +public: + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/nameplates.hpp b/src/game/client/components/nameplates.hpp deleted file mode 100644 index 2695f5ac..00000000 --- a/src/game/client/components/nameplates.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <game/client/component.hpp> - -class NAMEPLATES : public COMPONENT -{ - void render_nameplate( - const class NETOBJ_CHARACTER *prev_char, - const class NETOBJ_CHARACTER *player_char, - const class NETOBJ_PLAYER_INFO *player_info - ); - -public: - virtual void on_render(); -}; - diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index 61fcf738..99c2c721 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -1,155 +1,156 @@ -#include <base/math.hpp> -#include <engine/client/graphics.h> +#include <base/math.h> +#include <engine/graphics.h> -#include <game/generated/gc_data.hpp> -#include <game/client/render.hpp> -#include <game/gamecore.hpp> -#include "particles.hpp" +#include <game/generated/client_data.h> +#include <game/client/render.h> +#include <game/gamecore.h> +#include "particles.h" -PARTICLES::PARTICLES() +CParticles::CParticles() { - on_reset(); - render_trail.parts = this; - render_explosions.parts = this; - render_general.parts = this; + OnReset(); + m_RenderTrail.m_pParts = this; + m_RenderExplosions.m_pParts = this; + m_RenderGeneral.m_pParts = this; } -void PARTICLES::on_reset() +void CParticles::OnReset() { // reset particles for(int i = 0; i < MAX_PARTICLES; i++) { - particles[i].prev_part = i-1; - particles[i].next_part = i+1; + m_aParticles[i].m_PrevPart = i-1; + m_aParticles[i].m_NextPart = i+1; } - particles[0].prev_part = 0; - particles[MAX_PARTICLES-1].next_part = -1; - first_free = 0; + m_aParticles[0].m_PrevPart = 0; + m_aParticles[MAX_PARTICLES-1].m_NextPart = -1; + m_FirstFree = 0; for(int i = 0; i < NUM_GROUPS; i++) - first_part[i] = -1; + m_aFirstPart[i] = -1; } -void PARTICLES::add(int group, PARTICLE *part) +void CParticles::Add(int Group, CParticle *pPart) { - if (first_free == -1) + if (m_FirstFree == -1) return; // remove from the free list - int id = first_free; - first_free = particles[id].next_part; - particles[first_free].prev_part = -1; + int Id = m_FirstFree; + m_FirstFree = m_aParticles[Id].m_NextPart; + m_aParticles[m_FirstFree].m_PrevPart = -1; // copy data - particles[id] = *part; + m_aParticles[Id] = *pPart; // insert to the group list - particles[id].prev_part = -1; - particles[id].next_part = first_part[group]; - if(first_part[group] != -1) - particles[first_part[group]].prev_part = id; - first_part[group] = id; + m_aParticles[Id].m_PrevPart = -1; + m_aParticles[Id].m_NextPart = m_aFirstPart[Group]; + if(m_aFirstPart[Group] != -1) + m_aParticles[m_aFirstPart[Group]].m_PrevPart = Id; + m_aFirstPart[Group] = Id; // set some parameters - particles[id].life = 0; + m_aParticles[Id].m_Life = 0; } -void PARTICLES::update(float time_passed) +void CParticles::Update(float TimePassed) { - static float friction_fraction = 0; - friction_fraction += time_passed; + static float FrictionFraction = 0; + FrictionFraction += TimePassed; - if(friction_fraction > 2.0f) // safty messure - friction_fraction = 0; + if(FrictionFraction > 2.0f) // safty messure + FrictionFraction = 0; - int friction_count = 0; - while(friction_fraction > 0.05f) + int FrictionCount = 0; + while(FrictionFraction > 0.05f) { - friction_count++; - friction_fraction -= 0.05f; + FrictionCount++; + FrictionFraction -= 0.05f; } for(int g = 0; g < NUM_GROUPS; g++) { - int i = first_part[g]; + int i = m_aFirstPart[g]; while(i != -1) { - int next = particles[i].next_part; - //particles[i].vel += flow_get(particles[i].pos)*time_passed * particles[i].flow_affected; - particles[i].vel.y += particles[i].gravity*time_passed; + int Next = m_aParticles[i].m_NextPart; + //m_aParticles[i].vel += flow_get(m_aParticles[i].pos)*time_passed * m_aParticles[i].flow_affected; + m_aParticles[i].m_Vel.y += m_aParticles[i].m_Gravity*TimePassed; - for(int f = 0; f < friction_count; f++) // apply friction - particles[i].vel *= particles[i].friction; + for(int f = 0; f < FrictionCount; f++) // apply friction + m_aParticles[i].m_Vel *= m_aParticles[i].m_Friction; // move the point - vec2 vel = particles[i].vel*time_passed; - move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom(), NULL); - particles[i].vel = vel* (1.0f/time_passed); + vec2 Vel = m_aParticles[i].m_Vel*TimePassed; + Collision()->MovePoint(&m_aParticles[i].m_Pos, &Vel, 0.1f+0.9f*frandom(), NULL); + m_aParticles[i].m_Vel = Vel* (1.0f/TimePassed); - particles[i].life += time_passed; - particles[i].rot += time_passed * particles[i].rotspeed; + m_aParticles[i].m_Life += TimePassed; + m_aParticles[i].m_Rot += TimePassed * m_aParticles[i].m_Rotspeed; // check particle death - if(particles[i].life > particles[i].life_span) + if(m_aParticles[i].m_Life > m_aParticles[i].m_LifeSpan) { // remove it from the group list - if(particles[i].prev_part != -1) - particles[particles[i].prev_part].next_part = particles[i].next_part; + if(m_aParticles[i].m_PrevPart != -1) + m_aParticles[m_aParticles[i].m_PrevPart].m_NextPart = m_aParticles[i].m_NextPart; else - first_part[g] = particles[i].next_part; + m_aFirstPart[g] = m_aParticles[i].m_NextPart; - if(particles[i].next_part != -1) - particles[particles[i].next_part].prev_part = particles[i].prev_part; + if(m_aParticles[i].m_NextPart != -1) + m_aParticles[m_aParticles[i].m_NextPart].m_PrevPart = m_aParticles[i].m_PrevPart; // insert to the free list - if(first_free != -1) - particles[first_free].prev_part = i; - particles[i].prev_part = -1; - particles[i].next_part = first_free; - first_free = i; + if(m_FirstFree != -1) + m_aParticles[m_FirstFree].m_PrevPart = i; + m_aParticles[i].m_PrevPart = -1; + m_aParticles[i].m_NextPart = m_FirstFree; + m_FirstFree = i; } - i = next; + i = Next; } } } -void PARTICLES::on_render() +void CParticles::OnRender() { - static int64 lasttime = 0; + static int64 LastTime = 0; int64 t = time_get(); - update((float)((t-lasttime)/(double)time_freq())); - lasttime = t; + Update((float)((t-LastTime)/(double)time_freq())); + LastTime = t; } -void PARTICLES::render_group(int group) +void CParticles::RenderGroup(int Group) { Graphics()->BlendNormal(); //gfx_blend_additive(); - Graphics()->TextureSet(data->images[IMAGE_PARTICLES].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_PARTICLES].m_Id); Graphics()->QuadsBegin(); - int i = first_part[group]; + int i = m_aFirstPart[Group]; while(i != -1) { - RenderTools()->select_sprite(particles[i].spr); - float a = particles[i].life / particles[i].life_span; - vec2 p = particles[i].pos; - float size = mix(particles[i].start_size, particles[i].end_size, a); + RenderTools()->SelectSprite(m_aParticles[i].m_Spr); + float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan; + vec2 p = m_aParticles[i].m_Pos; + float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a); - Graphics()->QuadsSetRotation(particles[i].rot); + Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot); Graphics()->SetColor( - particles[i].color.r, - particles[i].color.g, - particles[i].color.b, - particles[i].color.a); // pow(a, 0.75f) * + m_aParticles[i].m_Color.r, + m_aParticles[i].m_Color.g, + m_aParticles[i].m_Color.b, + m_aParticles[i].m_Color.a); // pow(a, 0.75f) * - Graphics()->QuadsDraw(p.x, p.y, size, size); + IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size); + Graphics()->QuadsDraw(&QuadItem, 1); - i = particles[i].next_part; + i = m_aParticles[i].m_NextPart; } Graphics()->QuadsEnd(); Graphics()->BlendNormal(); diff --git a/src/game/client/components/particles.h b/src/game/client/components/particles.h new file mode 100644 index 00000000..af9a9203 --- /dev/null +++ b/src/game/client/components/particles.h @@ -0,0 +1,94 @@ +#ifndef GAME_CLIENT_COMPONENTS_PARTICLES_H +#define GAME_CLIENT_COMPONENTS_PARTICLES_H +#include <base/vmath.h> +#include <game/client/component.h> + +// particles +struct CParticle +{ + void SetDefault() + { + m_Vel = vec2(0,0); + m_LifeSpan = 0; + m_StartSize = 32; + m_EndSize = 32; + m_Rot = 0; + m_Rotspeed = 0; + m_Gravity = 0; + m_Friction = 0; + m_FlowAffected = 1.0f; + m_Color = vec4(1,1,1,1); + } + + vec2 m_Pos; + vec2 m_Vel; + + int m_Spr; + + float m_FlowAffected; + + float m_LifeSpan; + + float m_StartSize; + float m_EndSize; + + float m_Rot; + float m_Rotspeed; + + float m_Gravity; + float m_Friction; + + vec4 m_Color; + + // set by the particle system + float m_Life; + int m_PrevPart; + int m_NextPart; +}; + +class CParticles : public CComponent +{ + friend class CGameClient; +public: + enum + { + GROUP_PROJECTILE_TRAIL=0, + GROUP_EXPLOSIONS, + GROUP_GENERAL, + NUM_GROUPS + }; + + CParticles(); + + void Add(int Group, CParticle *pPart); + + virtual void OnReset(); + virtual void OnRender(); + +private: + + enum + { + MAX_PARTICLES=1024*8, + }; + + CParticle m_aParticles[MAX_PARTICLES]; + int m_FirstFree; + int m_aFirstPart[NUM_GROUPS]; + + void RenderGroup(int Group); + void Update(float TimePassed); + + template<int TGROUP> + class CRenderGroup : public CComponent + { + public: + CParticles *m_pParts; + virtual void OnRender() { m_pParts->RenderGroup(TGROUP); } + }; + + CRenderGroup<GROUP_PROJECTILE_TRAIL> m_RenderTrail; + CRenderGroup<GROUP_EXPLOSIONS> m_RenderExplosions; + CRenderGroup<GROUP_GENERAL> m_RenderGeneral; +}; +#endif diff --git a/src/game/client/components/particles.hpp b/src/game/client/components/particles.hpp deleted file mode 100644 index 6c466d94..00000000 --- a/src/game/client/components/particles.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -// particles -struct PARTICLE -{ - void set_default() - { - vel = vec2(0,0); - life_span = 0; - start_size = 32; - end_size = 32; - rot = 0; - rotspeed = 0; - gravity = 0; - friction = 0; - flow_affected = 1.0f; - color = vec4(1,1,1,1); - } - - vec2 pos; - vec2 vel; - - int spr; - - float flow_affected; - - float life_span; - - float start_size; - float end_size; - - float rot; - float rotspeed; - - float gravity; - float friction; - - vec4 color; - - // set by the particle system - float life; - int prev_part; - int next_part; -}; - -class PARTICLES : public COMPONENT -{ - friend class GAMECLIENT; -public: - enum - { - GROUP_PROJECTILE_TRAIL=0, - GROUP_EXPLOSIONS, - GROUP_GENERAL, - NUM_GROUPS - }; - - PARTICLES(); - - void add(int group, PARTICLE *part); - - virtual void on_reset(); - virtual void on_render(); - -private: - - enum - { - MAX_PARTICLES=1024*8, - }; - - PARTICLE particles[MAX_PARTICLES]; - int first_free; - int first_part[NUM_GROUPS]; - - void render_group(int group); - void update(float time_passed); - - template<int TGROUP> - class RENDER_GROUP : public COMPONENT - { - public: - PARTICLES *parts; - virtual void on_render() { parts->render_group(TGROUP); } - }; - - RENDER_GROUP<GROUP_PROJECTILE_TRAIL> render_trail; - RENDER_GROUP<GROUP_EXPLOSIONS> render_explosions; - RENDER_GROUP<GROUP_GENERAL> render_general; -}; diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index e1fee3e8..8ad7b0cb 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -1,147 +1,269 @@ -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> - -#include <game/gamecore.hpp> // get_angle -#include <game/client/animstate.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/ui.hpp> -#include <game/client/render.hpp> - -#include <game/client/components/flow.hpp> -#include <game/client/components/skins.hpp> -#include <game/client/components/effects.hpp> -#include <game/client/components/sounds.hpp> -#include <game/client/components/controls.hpp> - -#include "players.hpp" - -void PLAYERS::render_hand(TEE_RENDER_INFO *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset) +#include <engine/graphics.h> +#include <engine/shared/config.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> + +#include <game/gamecore.h> // get_angle +#include <game/client/animstate.h> +#include <game/client/gameclient.h> +#include <game/client/ui.h> +#include <game/client/render.h> + +#include <game/client/components/flow.h> +#include <game/client/components/skins.h> +#include <game/client/components/effects.h> +#include <game/client/components/sounds.h> +#include <game/client/components/controls.h> + +#include "players.h" + +void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset) { // for drawing hand //const skin *s = skin_get(skin_id); - float basesize = 10.0f; + float BaseSize = 10.0f; //dir = normalize(hook_pos-pos); - vec2 hand_pos = center_pos + dir; - float angle = get_angle(dir); - if (dir.x < 0) - angle -= angle_offset; + vec2 HandPos = CenterPos + Dir; + float Angle = GetAngle(Dir); + if (Dir.x < 0) + Angle -= AngleOffset; else - angle += angle_offset; + Angle += AngleOffset; - vec2 dirx = dir; - vec2 diry(-dir.y,dir.x); + vec2 DirX = Dir; + vec2 DirY(-Dir.y,Dir.x); - if (dir.x < 0) - diry = -diry; + if (Dir.x < 0) + DirY = -DirY; - hand_pos += dirx * post_rot_offset.x; - hand_pos += diry * post_rot_offset.y; + HandPos += DirX * PostRotOffset.x; + HandPos += DirY * PostRotOffset.y; - //Graphics()->TextureSet(data->images[IMAGE_CHAR_DEFAULT].id); - Graphics()->TextureSet(info->texture); + //Graphics()->TextureSet(data->m_aImages[IMAGE_CHAR_DEFAULT].id); + Graphics()->TextureSet(pInfo->m_Texture); Graphics()->QuadsBegin(); - Graphics()->SetColor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a); + Graphics()->SetColor(pInfo->m_ColorBody.r, pInfo->m_ColorBody.g, pInfo->m_ColorBody.b, pInfo->m_ColorBody.a); // two passes for (int i = 0; i < 2; i++) { - bool outline = i == 0; + bool OutLine = i == 0; - RenderTools()->select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0); - Graphics()->QuadsSetRotation(angle); - Graphics()->QuadsDraw(hand_pos.x, hand_pos.y, 2*basesize, 2*basesize); + RenderTools()->SelectSprite(OutLine?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0); + Graphics()->QuadsSetRotation(Angle); + IGraphics::CQuadItem QuadItem(HandPos.x, HandPos.y, 2*BaseSize, 2*BaseSize); + Graphics()->QuadsDraw(&QuadItem, 1); } Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); } -inline float normalize_angular(float f) +inline float NormalizeAngular(float f) { return fmod(f+pi*2, pi*2); } -inline float angular_mix_direction(float src, float dst) { return sinf(dst-src) >0?1:-1; } -inline float angular_distance(float src, float dst) { return asinf(sinf(dst-src)); } +inline float AngularMixDirection (float Src, float Dst) { return sinf(Dst-Src) >0?1:-1; } +inline float AngularDistance(float Src, float Dst) { return asinf(sinf(Dst-Src)); } -inline float angular_approach(float src, float dst, float amount) +inline float AngularApproach(float Src, float Dst, float Amount) { - float d = angular_mix_direction(src, dst); - float n = src + amount*d; - if(angular_mix_direction(n, dst) != d) - return dst; + float d = AngularMixDirection (Src, Dst); + float n = Src + Amount*d; + if(AngularMixDirection (n, Dst) != d) + return Dst; return n; } -void PLAYERS::render_player( - const NETOBJ_CHARACTER *prev_char, - const NETOBJ_CHARACTER *player_char, - const NETOBJ_PLAYER_INFO *prev_info, - const NETOBJ_PLAYER_INFO *player_info +void CPlayers::RenderHook( + const CNetObj_Character *pPrevChar, + const CNetObj_Character *pPlayerChar, + const CNetObj_PlayerInfo *pPrevInfo, + const CNetObj_PlayerInfo *pPlayerInfo ) { - NETOBJ_CHARACTER prev; - NETOBJ_CHARACTER player; - prev = *prev_char; - player = *player_char; + CNetObj_Character Prev; + CNetObj_Character Player; + Prev = *pPrevChar; + Player = *pPlayerChar; - NETOBJ_PLAYER_INFO info = *player_info; - TEE_RENDER_INFO render_info = gameclient.clients[info.cid].render_info; + CNetObj_PlayerInfo pInfo = *pPlayerInfo; + CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientId].m_RenderInfo; // check for teamplay modes - bool is_teamplay = false; - bool new_tick = gameclient.new_tick; - if(gameclient.snap.gameobj) - is_teamplay = (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0; + bool IsTeamplay = false; + if(m_pClient->m_Snap.m_pGameobj) + IsTeamplay = (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0; // check for ninja - if (player.weapon == WEAPON_NINJA) + if (Player.m_Weapon == WEAPON_NINJA) { // change the skin for the player to the ninja - int skin = gameclient.skins->find("x_ninja"); - if(skin != -1) + int Skin = m_pClient->m_pSkins->Find("x_ninja"); + if(Skin != -1) { - if(is_teamplay) - render_info.texture = gameclient.skins->get(skin)->color_texture; + if(IsTeamplay) + RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; else { - render_info.texture = gameclient.skins->get(skin)->org_texture; - render_info.color_body = vec4(1,1,1,1); - render_info.color_feet = vec4(1,1,1,1); + RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; + RenderInfo.m_ColorBody = vec4(1,1,1,1); + RenderInfo.m_ColorFeet = vec4(1,1,1,1); + } + } + } + + float IntraTick = Client()->IntraGameTick(); + + if(Player.m_Health < 0) // dont render dead players + return; + + // set size + RenderInfo.m_Size = 64.0f; + + + // use preditect players if needed + if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) + { + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + { + } + else + { + // apply predicted results + m_pClient->m_PredictedChar.Write(&Player); + m_pClient->m_PredictedPrevChar.Write(&Prev); + IntraTick = Client()->PredIntraGameTick(); + } + } + + vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); + + if(Prev.m_Health < 0) // Don't flicker from previous position + Position = vec2(Player.m_X, Player.m_Y); + + // draw hook + if (Prev.m_HookState>0 && Player.m_HookState>0) + { + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); + Graphics()->QuadsBegin(); + //Graphics()->QuadsBegin(); + + vec2 Pos = Position; + vec2 HookPos; + + if(pPlayerChar->m_HookedPlayer != -1) + { + if(m_pClient->m_Snap.m_pLocalInfo && pPlayerChar->m_HookedPlayer == m_pClient->m_Snap.m_pLocalInfo->m_ClientId) + { + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) // only use prediction if needed + HookPos = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y); + else + HookPos = mix(vec2(m_pClient->m_PredictedPrevChar.m_Pos.x, m_pClient->m_PredictedPrevChar.m_Pos.y), + vec2(m_pClient->m_PredictedChar.m_Pos.x, m_pClient->m_PredictedChar.m_Pos.y), Client()->PredIntraGameTick()); + } + else + HookPos = mix(vec2(pPrevChar->m_HookX, pPrevChar->m_HookY), vec2(pPlayerChar->m_HookX, pPlayerChar->m_HookY), Client()->IntraGameTick()); + } + else + HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick); + + float d = distance(Pos, HookPos); + vec2 Dir = normalize(Pos-HookPos); + + Graphics()->QuadsSetRotation(GetAngle(Dir)+pi); + + // render head + RenderTools()->SelectSprite(SPRITE_HOOK_HEAD); + IGraphics::CQuadItem QuadItem(HookPos.x, HookPos.y, 24,16); + Graphics()->QuadsDraw(&QuadItem, 1); + + // render chain + RenderTools()->SelectSprite(SPRITE_HOOK_CHAIN); + IGraphics::CQuadItem Array[1024]; + int i = 0; + for(float f = 24; f < d && i < 1024; f += 24, i++) + { + vec2 p = HookPos + Dir*f; + Array[i] = IGraphics::CQuadItem(p.x, p.y,24,16); + } + + Graphics()->QuadsDraw(Array, i); + Graphics()->QuadsSetRotation(0); + Graphics()->QuadsEnd(); + + RenderHand(&RenderInfo, Position, normalize(HookPos-Pos), -pi/2, vec2(20, 0)); + } +} + +void CPlayers::RenderPlayer( + const CNetObj_Character *pPrevChar, + const CNetObj_Character *pPlayerChar, + const CNetObj_PlayerInfo *pPrevInfo, + const CNetObj_PlayerInfo *pPlayerInfo + ) +{ + CNetObj_Character Prev; + CNetObj_Character Player; + Prev = *pPrevChar; + Player = *pPlayerChar; + + CNetObj_PlayerInfo pInfo = *pPlayerInfo; + CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientId].m_RenderInfo; + + // check for teamplay modes + bool IsTeamplay = false; + bool NewTick = m_pClient->m_NewTick; + if(m_pClient->m_Snap.m_pGameobj) + IsTeamplay = (m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) != 0; + + // check for ninja + if (Player.m_Weapon == WEAPON_NINJA) + { + // change the skin for the player to the ninja + int Skin = m_pClient->m_pSkins->Find("x_ninja"); + if(Skin != -1) + { + if(IsTeamplay) + RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; + else + { + RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; + RenderInfo.m_ColorBody = vec4(1,1,1,1); + RenderInfo.m_ColorFeet = vec4(1,1,1,1); } } } // set size - render_info.size = 64.0f; + RenderInfo.m_Size = 64.0f; - float intratick = client_intratick(); + float IntraTick = Client()->IntraGameTick(); - if(player.health < 0) // dont render dead players + if(Player.m_Health < 0) // dont render dead players return; - float angle = mix((float)prev.angle, (float)player.angle, intratick)/256.0f; + float Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f; //float angle = 0; - if(info.local && client_state() != CLIENTSTATE_DEMOPLAYBACK) + if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK) { // just use the direct input if it's local player we are rendering - angle = get_angle(gameclient.controls->mouse_pos); + Angle = GetAngle(m_pClient->m_pControls->m_MousePos); } else { /* - float mixspeed = client_frametime()*2.5f; + float mixspeed = Client()->FrameTime()*2.5f; if(player.attacktick != prev.attacktick) // shooting boosts the mixing speed mixspeed *= 15.0f; // move the delta on a constant speed on a x^2 curve - float current = gameclient.clients[info.cid].angle; + float current = g_GameClient.m_aClients[info.cid].angle; float target = player.angle/256.0f; float delta = angular_distance(current, target); float sign = delta < 0 ? -1 : 1; @@ -153,342 +275,305 @@ void PLAYERS::render_player( else angle = angular_approach(current, target, fabs(delta-new_delta)); - gameclient.clients[info.cid].angle = angle;*/ + g_GameClient.m_aClients[info.cid].angle = angle;*/ } // use preditect players if needed - if(info.local && config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK) + if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!gameclient.snap.local_character || (gameclient.snap.local_character->health < 0) || (gameclient.snap.gameobj && gameclient.snap.gameobj->game_over)) + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) { } else { // apply predicted results - gameclient.predicted_char.write(&player); - gameclient.predicted_prev_char.write(&prev); - intratick = client_predintratick(); - new_tick = gameclient.new_predicted_tick; + m_pClient->m_PredictedChar.Write(&Player); + m_pClient->m_PredictedPrevChar.Write(&Prev); + IntraTick = Client()->PredIntraGameTick(); + NewTick = m_pClient->m_NewPredictedTick; } } - vec2 direction = get_direction((int)(angle*256.0f)); - vec2 position = mix(vec2(prev.x, prev.y), vec2(player.x, player.y), intratick); - vec2 vel = mix(vec2(prev.vx/256.0f, prev.vy/256.0f), vec2(player.vx/256.0f, player.vy/256.0f), intratick); + vec2 Direction = GetDirection((int)(Angle*256.0f)); + vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); + vec2 Vel = mix(vec2(Prev.m_VelX/256.0f, Prev.m_VelY/256.0f), vec2(Player.m_VelX/256.0f, Player.m_VelY/256.0f), IntraTick); - gameclient.flow->add(position, vel*100.0f, 10.0f); + m_pClient->m_pFlow->Add(Position, Vel*100.0f, 10.0f); - render_info.got_airjump = player.jumped&2?0:1; + RenderInfo.m_GotAirJump = Player.m_Jumped&2?0:1; // detect events - if(new_tick) + if(NewTick) { // detect air jump - if(!render_info.got_airjump && !(prev.jumped&2)) - gameclient.effects->air_jump(position); + if(!RenderInfo.m_GotAirJump && !(Prev.m_Jumped&2)) + m_pClient->m_pEffects->AirJump(Position); } - if(prev.health < 0) // Don't flicker from previous position - position = vec2(player.x, player.y); + if(Prev.m_Health < 0) // Don't flicker from previous position + Position = vec2(Player.m_X, Player.m_Y); - bool stationary = player.vx < 1 && player.vx > -1; - bool inair = col_check_point(player.x, player.y+16) == 0; - bool want_other_dir = (player.direction == -1 && vel.x > 0) || (player.direction == 1 && vel.x < 0); + bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1; + bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16); + bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0); // evaluate animation - float walk_time = fmod(position.x, 100.0f)/100.0f; - ANIMSTATE state; - state.set(&data->animations[ANIM_BASE], 0); - - if(inair) - state.add(&data->animations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here - else if(stationary) - state.add(&data->animations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here - else if(!want_other_dir) - state.add(&data->animations[ANIM_WALK], walk_time, 1.0f); - - if (player.weapon == WEAPON_HAMMER) + float WalkTime = fmod(Position.x, 100.0f)/100.0f; + CAnimState State; + State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0); + + if(InAir) + State.Add(&g_pData->m_aAnimations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here + else if(Stationary) + State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here + else if(!WantOtherDir) + State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f); + + if (Player.m_Weapon == WEAPON_HAMMER) { - float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime(); - state.add(&data->animations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f); + float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f); } - if (player.weapon == WEAPON_NINJA) + if (Player.m_Weapon == WEAPON_NINJA) { - float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime(); - state.add(&data->animations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f); + float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f); } // do skidding - if(!inair && want_other_dir && length(vel*50) > 500.0f) + if(!InAir && WantOtherDir && length(Vel*50) > 500.0f) { - static int64 skid_sound_time = 0; - if(time_get()-skid_sound_time > time_freq()/10) + static int64 SkidSoundTime = 0; + if(time_get()-SkidSoundTime > time_freq()/10) { - gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, position); - skid_sound_time = time_get(); + m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position); + SkidSoundTime = time_get(); } - gameclient.effects->skidtrail( - position+vec2(-player.direction*6,12), - vec2(-player.direction*100*length(vel),-50) + m_pClient->m_pEffects->SkidTrail( + Position+vec2(-Player.m_Direction*6,12), + vec2(-Player.m_Direction*100*length(Vel),-50) ); } - // draw hook - if (prev.hook_state>0 && player.hook_state>0) - { - Graphics()->TextureSet(data->images[IMAGE_GAME].id); - Graphics()->QuadsBegin(); - //Graphics()->QuadsBegin(); - - vec2 pos = position; - vec2 hook_pos; - - if(player_char->hooked_player != -1) - { - if(gameclient.snap.local_info && player_char->hooked_player == gameclient.snap.local_info->cid) - { - hook_pos = mix(vec2(gameclient.predicted_prev_char.pos.x, gameclient.predicted_prev_char.pos.y), - vec2(gameclient.predicted_char.pos.x, gameclient.predicted_char.pos.y), client_predintratick()); - } - else - hook_pos = mix(vec2(prev_char->hook_x, prev_char->hook_y), vec2(player_char->hook_x, player_char->hook_y), client_intratick()); - } - else - hook_pos = mix(vec2(prev.hook_x, prev.hook_y), vec2(player.hook_x, player.hook_y), intratick); - - float d = distance(pos, hook_pos); - vec2 dir = normalize(pos-hook_pos); - - Graphics()->QuadsSetRotation(get_angle(dir)+pi); - - // render head - RenderTools()->select_sprite(SPRITE_HOOK_HEAD); - Graphics()->QuadsDraw(hook_pos.x, hook_pos.y, 24,16); - - // render chain - RenderTools()->select_sprite(SPRITE_HOOK_CHAIN); - int i = 0; - for(float f = 24; f < d && i < 1024; f += 24, i++) - { - vec2 p = hook_pos + dir*f; - Graphics()->QuadsDraw(p.x, p.y,24,16); - } - - Graphics()->QuadsSetRotation(0); - Graphics()->QuadsEnd(); - - render_hand(&render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0)); - } - // draw gun { - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - Graphics()->QuadsSetRotation(state.attach.angle*pi*2+angle); + Graphics()->QuadsSetRotation(State.GetAttach()->m_Angle*pi*2+Angle); // normal weapons - int iw = clamp(player.weapon, 0, NUM_WEAPONS-1); - RenderTools()->select_sprite(data->weapons.id[iw].sprite_body, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0); + int iw = clamp(Player.m_Weapon, 0, NUM_WEAPONS-1); + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_pSpriteBody, Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0); - vec2 dir = direction; - float recoil = 0.0f; + vec2 Dir = Direction; + float Recoil = 0.0f; vec2 p; - if (player.weapon == WEAPON_HAMMER) + if (Player.m_Weapon == WEAPON_HAMMER) { // Static position for hammer - p = position + vec2(state.attach.x, state.attach.y); - p.y += data->weapons.id[iw].offsety; + p = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y); + p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; // if attack is under way, bash stuffs - if(direction.x < 0) + if(Direction.x < 0) { - Graphics()->QuadsSetRotation(-pi/2-state.attach.angle*pi*2); - p.x -= data->weapons.id[iw].offsetx; + Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2); + p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx; } else { - Graphics()->QuadsSetRotation(-pi/2+state.attach.angle*pi*2); + Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2); } - RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size); + RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize); } - else if (player.weapon == WEAPON_NINJA) + else if (Player.m_Weapon == WEAPON_NINJA) { - p = position; - p.y += data->weapons.id[iw].offsety; + p = Position; + p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; - if(direction.x < 0) + if(Direction.x < 0) { - Graphics()->QuadsSetRotation(-pi/2-state.attach.angle*pi*2); - p.x -= data->weapons.id[iw].offsetx; - gameclient.effects->powerupshine(p+vec2(32,0), vec2(32,12)); + Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2); + p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx; + m_pClient->m_pEffects->PowerupShine(p+vec2(32,0), vec2(32,12)); } else { - Graphics()->QuadsSetRotation(-pi/2+state.attach.angle*pi*2); - gameclient.effects->powerupshine(p-vec2(32,0), vec2(32,12)); + Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2); + m_pClient->m_pEffects->PowerupShine(p-vec2(32,0), vec2(32,12)); } - RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size); + RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize); // HADOKEN - if ((client_tick()-player.attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons.id[iw].num_sprite_muzzles) + if ((Client()->GameTick()-Player.m_AttackTick) <= (SERVER_TICK_SPEED / 6) && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles) { - int itex = rand() % data->weapons.id[iw].num_sprite_muzzles; - float alpha = 1.0f; - if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex]) + int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; + float Alpha = 1.0f; + if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) { - vec2 dir = vec2(player_char->x,player_char->y) - vec2(prev_char->x, prev_char->y); - dir = normalize(dir); - float hadokenangle = get_angle(dir); - Graphics()->QuadsSetRotation(hadokenangle); + vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y); + Dir = normalize(Dir); + float HadOkenAngle = GetAngle(Dir); + Graphics()->QuadsSetRotation(HadOkenAngle ); //float offsety = -data->weapons[iw].muzzleoffsety; - RenderTools()->select_sprite(data->weapons.id[iw].sprite_muzzles[itex], 0); - vec2 diry(-dir.y,dir.x); - p = position; - float offsetx = data->weapons.id[iw].muzzleoffsetx; - p -= dir * offsetx; - RenderTools()->draw_sprite(p.x, p.y, 160.0f); + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], 0); + vec2 DirY(-Dir.y,Dir.x); + p = Position; + float OffsetX = g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx; + p -= Dir * OffsetX; + RenderTools()->DrawSprite(p.x, p.y, 160.0f); } } } else { // TODO: should be an animation - recoil = 0; - float a = (client_tick()-player.attacktick+intratick)/5.0f; + Recoil = 0; + float a = (Client()->GameTick()-Player.m_AttackTick+IntraTick)/5.0f; if(a < 1) - recoil = sinf(a*pi); - p = position + dir * data->weapons.id[iw].offsetx - dir*recoil*10.0f; - p.y += data->weapons.id[iw].offsety; - RenderTools()->draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size); + Recoil = sinf(a*pi); + p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir*Recoil*10.0f; + p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; + RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize); } - if (player.weapon == WEAPON_GUN || player.weapon == WEAPON_SHOTGUN) + if (Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN) { // check if we're firing stuff - if(data->weapons.id[iw].num_sprite_muzzles)//prev.attackticks) + if(g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)//prev.attackticks) { - float alpha = 0.0f; - int phase1tick = (client_tick() - player.attacktick); - if (phase1tick < (data->weapons.id[iw].muzzleduration + 3)) + float Alpha = 0.0f; + int Phase1Tick = (Client()->GameTick() - Player.m_AttackTick); + if (Phase1Tick < (g_pData->m_Weapons.m_aId[iw].m_Muzzleduration + 3)) { - float t = ((((float)phase1tick) + intratick)/(float)data->weapons.id[iw].muzzleduration); - alpha = LERP(2.0, 0.0f, min(1.0f,max(0.0f,t))); + float t = ((((float)Phase1Tick) + IntraTick)/(float)g_pData->m_Weapons.m_aId[iw].m_Muzzleduration); + Alpha = mix(2.0f, 0.0f, min(1.0f,max(0.0f,t))); } - int itex = rand() % data->weapons.id[iw].num_sprite_muzzles; - if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex]) + int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; + if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) { - float offsety = -data->weapons.id[iw].muzzleoffsety; - RenderTools()->select_sprite(data->weapons.id[iw].sprite_muzzles[itex], direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0); - if(direction.x < 0) - offsety = -offsety; + float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety; + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0); + if(Direction.x < 0) + OffsetY = -OffsetY; - vec2 diry(-dir.y,dir.x); - vec2 muzzlepos = p + dir * data->weapons.id[iw].muzzleoffsetx + diry * offsety; + vec2 DirY(-Dir.y,Dir.x); + vec2 MuzzlePos = p + Dir * g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx + DirY * OffsetY; - RenderTools()->draw_sprite(muzzlepos.x, muzzlepos.y, data->weapons.id[iw].visual_size); + RenderTools()->DrawSprite(MuzzlePos.x, MuzzlePos.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize); } } } Graphics()->QuadsEnd(); - switch (player.weapon) + switch (Player.m_Weapon) { - case WEAPON_GUN: render_hand(&render_info, p, direction, -3*pi/4, vec2(-15, 4)); break; - case WEAPON_SHOTGUN: render_hand(&render_info, p, direction, -pi/2, vec2(-5, 4)); break; - case WEAPON_GRENADE: render_hand(&render_info, p, direction, -pi/2, vec2(-4, 7)); break; + case WEAPON_GUN: RenderHand(&RenderInfo, p, Direction, -3*pi/4, vec2(-15, 4)); break; + case WEAPON_SHOTGUN: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-5, 4)); break; + case WEAPON_GRENADE: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-4, 7)); break; } } // render the "shadow" tee - if(info.local && config.debug) + if(pInfo.m_Local && g_Config.m_Debug) { - vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick()); - TEE_RENDER_INFO ghost = render_info; - ghost.color_body.a = 0.5f; - ghost.color_feet.a = 0.5f; - RenderTools()->RenderTee(&state, &ghost, player.emote, direction, ghost_position); // render ghost + vec2 GhostPosition = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick()); + CTeeRenderInfo Ghost = RenderInfo; + Ghost.m_ColorBody.a = 0.5f; + Ghost.m_ColorFeet.a = 0.5f; + RenderTools()->RenderTee(&State, &Ghost, Player.m_Emote, Direction, GhostPosition); // render ghost } - render_info.size = 64.0f; // force some settings - render_info.color_body.a = 1.0f; - render_info.color_feet.a = 1.0f; - RenderTools()->RenderTee(&state, &render_info, player.emote, direction, position); + RenderInfo.m_Size = 64.0f; // force some settings + RenderInfo.m_ColorBody.a = 1.0f; + RenderInfo.m_ColorFeet.a = 1.0f; + RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position); - if(player.player_state == PLAYERSTATE_CHATTING) + if(Player.m_PlayerState == PLAYERSTATE_CHATTING) { - Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); - RenderTools()->select_sprite(SPRITE_DOTDOT); - Graphics()->QuadsDraw(position.x + 24, position.y - 40, 64,64); + RenderTools()->SelectSprite(SPRITE_DOTDOT); + IGraphics::CQuadItem QuadItem(Position.x + 24, Position.y - 40, 64,64); + Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); } - if (gameclient.clients[info.cid].emoticon_start != -1 && gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() > client_tick()) + if (m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart != -1 && m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick()) { - Graphics()->TextureSet(data->images[IMAGE_EMOTICONS].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); - int since_start = client_tick() - gameclient.clients[info.cid].emoticon_start; - int from_end = gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() - client_tick(); + int SinceStart = Client()->GameTick() - m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart; + int FromEnd = m_pClient->m_aClients[pInfo.m_ClientId].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(); float a = 1; - if (from_end < client_tickspeed() / 5) - a = from_end / (client_tickspeed() / 5.0); + if (FromEnd < Client()->GameTickSpeed() / 5) + a = FromEnd / (Client()->GameTickSpeed() / 5.0); float h = 1; - if (since_start < client_tickspeed() / 10) - h = since_start / (client_tickspeed() / 10.0); + if (SinceStart < Client()->GameTickSpeed() / 10) + h = SinceStart / (Client()->GameTickSpeed() / 10.0); - float wiggle = 0; - if (since_start < client_tickspeed() / 5) - wiggle = since_start / (client_tickspeed() / 5.0); + float Wiggle = 0; + if (SinceStart < Client()->GameTickSpeed() / 5) + Wiggle = SinceStart / (Client()->GameTickSpeed() / 5.0); - float wiggle_angle = sin(5*wiggle); + float WiggleAngle = sinf(5*Wiggle); - Graphics()->QuadsSetRotation(pi/6*wiggle_angle); + Graphics()->QuadsSetRotation(pi/6*WiggleAngle); Graphics()->SetColor(1.0f,1.0f,1.0f,a); // client_datas::emoticon is an offset from the first emoticon - RenderTools()->select_sprite(SPRITE_OOP + gameclient.clients[info.cid].emoticon); - Graphics()->QuadsDraw(position.x, position.y - 23 - 32*h, 64, 64*h); + RenderTools()->SelectSprite(SPRITE_OOP + m_pClient->m_aClients[pInfo.m_ClientId].m_Emoticon); + IGraphics::CQuadItem QuadItem(Position.x, Position.y - 23 - 32*h, 64, 64*h); + Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); } } -void PLAYERS::on_render() +void CPlayers::OnRender() { // render other players in two passes, first pass we render the other, second pass we render our self - for(int p = 0; p < 2; p++) + for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters - if(!gameclient.snap.characters[i].active) + if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; - const void *prev_info = snap_find_item(SNAP_PREV, NETOBJTYPE_PLAYER_INFO, i); - const void *info = snap_find_item(SNAP_CURRENT, NETOBJTYPE_PLAYER_INFO, i); + const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); + const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); - if(prev_info && info) + if(pPrevInfo && pInfo) { // - bool local = ((const NETOBJ_PLAYER_INFO *)info)->local !=0; - if(p == 0 && local) continue; - if(p == 1 && !local) continue; + bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0; + if((p % 2) == 0 && Local) continue; + if((p % 2) == 1 && !Local) continue; - NETOBJ_CHARACTER prev_char = gameclient.snap.characters[i].prev; - NETOBJ_CHARACTER cur_char = gameclient.snap.characters[i].cur; - - render_player( - &prev_char, - &cur_char, - (const NETOBJ_PLAYER_INFO *)prev_info, - (const NETOBJ_PLAYER_INFO *)info - ); + CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; + CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; + + if(p<2) + RenderHook( + &PrevChar, + &CurChar, + (const CNetObj_PlayerInfo *)pPrevInfo, + (const CNetObj_PlayerInfo *)pInfo + ); + else + RenderPlayer( + &PrevChar, + &CurChar, + (const CNetObj_PlayerInfo *)pPrevInfo, + (const CNetObj_PlayerInfo *)pInfo + ); } } } diff --git a/src/game/client/components/players.h b/src/game/client/components/players.h new file mode 100644 index 00000000..57501380 --- /dev/null +++ b/src/game/client/components/players.h @@ -0,0 +1,25 @@ +#ifndef GAME_CLIENT_COMPONENTS_PLAYERS_H +#define GAME_CLIENT_COMPONENTS_PLAYERS_H +#include <game/client/component.h> + +class CPlayers : public CComponent +{ + void RenderHand(class CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset); + void RenderPlayer( + const class CNetObj_Character *pPrevChar, + const class CNetObj_Character *pPlayerChar, + const class CNetObj_PlayerInfo *pPrevInfo, + const class CNetObj_PlayerInfo *pPlayerInfo + ); + void RenderHook( + const CNetObj_Character *pPrevChar, + const CNetObj_Character *pPlayerChar, + const CNetObj_PlayerInfo *pPrevInfo, + const CNetObj_PlayerInfo *pPlayerInfo + ); + +public: + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/players.hpp b/src/game/client/components/players.hpp deleted file mode 100644 index bdce91de..00000000 --- a/src/game/client/components/players.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#include <game/client/component.hpp> - -class PLAYERS : public COMPONENT -{ - void render_hand(class TEE_RENDER_INFO *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset); - void render_player( - const class NETOBJ_CHARACTER *prev_char, - const class NETOBJ_CHARACTER *player_char, - const class NETOBJ_PLAYER_INFO *prev_info, - const class NETOBJ_PLAYER_INFO *player_info - ); - -public: - virtual void on_render(); -}; - diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index e8db1aed..b7e8aa9a 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -1,36 +1,37 @@ -#include <string.h> -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/animstate.hpp> -#include <game/client/render.hpp> -#include <game/client/components/motd.hpp> -#include "scoreboard.hpp" - - -SCOREBOARD::SCOREBOARD() +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/shared/config.h> +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> +#include <game/client/gameclient.h> +#include <game/client/animstate.h> +#include <game/client/render.h> +#include <game/client/components/motd.h> +#include <game/localization.h> +#include "scoreboard.h" + + +CScoreboard::CScoreboard() { - on_reset(); + OnReset(); } -void SCOREBOARD::con_key_scoreboard(void *result, void *user_data) +void CScoreboard::ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData) { - ((SCOREBOARD *)user_data)->active = console_arg_int(result, 0) != 0; + ((CScoreboard *)pUserData)->m_Active = pResult->GetInteger(0) != 0; } -void SCOREBOARD::on_reset() +void CScoreboard::OnReset() { - active = false; + m_Active = false; } -void SCOREBOARD::on_console_init() +void CScoreboard::OnConsoleInit() { - MACRO_REGISTER_COMMAND("+scoreboard", "", CFGFLAG_CLIENT, con_key_scoreboard, this, "Show scoreboard"); + Console()->Register("+scoreboard", "", CFGFLAG_CLIENT, ConKeyScoreboard, this, "Show scoreboard"); } -void SCOREBOARD::render_goals(float x, float y, float w) +void CScoreboard::RenderGoals(float x, float y, float w) { float h = 50.0f; @@ -38,74 +39,77 @@ void SCOREBOARD::render_goals(float x, float y, float w) Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 10.0f); + RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 10.0f); Graphics()->QuadsEnd(); // render goals //y = ystart+h-54; float tw = 0.0f; - if(gameclient.snap.gameobj && gameclient.snap.gameobj->score_limit) + if(m_pClient->m_Snap.m_pGameobj) { - char buf[64]; - str_format(buf, sizeof(buf), "%s: %d", localize("Score limit"), gameclient.snap.gameobj->score_limit); - gfx_text(0, x+20.0f, y, 22.0f, buf, -1); - tw += gfx_text_width(0, 22.0f, buf, -1); - } - if(gameclient.snap.gameobj && gameclient.snap.gameobj->time_limit) - { - char buf[64]; - str_format(buf, sizeof(buf), "%s: %d min", localize("Time limit"), gameclient.snap.gameobj->time_limit); - gfx_text(0, x+220.0f, y, 22.0f, buf, -1); - tw += gfx_text_width(0, 22.0f, buf, -1); - } - if(gameclient.snap.gameobj && gameclient.snap.gameobj->round_num && gameclient.snap.gameobj->round_current) - { - char buf[64]; - str_format(buf, sizeof(buf), "%s %d/%d", localize("Round"), gameclient.snap.gameobj->round_current, gameclient.snap.gameobj->round_num); - gfx_text(0, x+450.0f, y, 22.0f, buf, -1); - - /*[48c3fd4c][game/scoreboard]: timelimit x:219.428558 - [48c3fd4c][game/scoreboard]: round x:453.142822*/ + if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit); + TextRender()->Text(0, x+20.0f, y, 22.0f, aBuf, -1); + tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + } + if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s: %d min", Localize("Time limit"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit); + TextRender()->Text(0, x+220.0f, y, 22.0f, aBuf, -1); + tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + } + if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Round"), m_pClient->m_Snap.m_pGameobj->m_RoundCurrent, m_pClient->m_Snap.m_pGameobj->m_RoundNum); + TextRender()->Text(0, x+450.0f, y, 22.0f, aBuf, -1); + + /*[48c3fd4c][game/scoreboard]: timelimit x:219.428558 + [48c3fd4c][game/scoreboard]: round x:453.142822*/ + } } } -void SCOREBOARD::render_spectators(float x, float y, float w) +void CScoreboard::RenderSpectators(float x, float y, float w) { - char buffer[1024*4]; - int count = 0; + char aBuffer[1024*4]; + int Count = 0; float h = 120.0f; - str_format(buffer, sizeof(buffer), "%s: ", localize("Spectators")); + str_format(aBuffer, sizeof(aBuffer), "%s: ", Localize("Spectators")); Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 10.0f); + RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 10.0f); Graphics()->QuadsEnd(); - for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) + for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - if(item.type == NETOBJTYPE_PLAYER_INFO) + if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { - const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data; - if(info->team == -1) + const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; + if(pInfo->m_Team == -1) { - if(count) - strcat(buffer, ", "); - strcat(buffer, gameclient.clients[info->cid].name); - count++; + if(Count) + str_append(aBuffer, ", ", sizeof(aBuffer)); + str_append(aBuffer, m_pClient->m_aClients[pInfo->m_ClientId].m_aName, sizeof(aBuffer)); + Count++; } } } - gfx_text(0, x+10, y, 32, buffer, (int)w-20); + TextRender()->Text(0, x+10, y, 32, aBuffer, (int)w-20); } -void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const char *title) +void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle) { //float ystart = y; float h = 750.0f; @@ -114,202 +118,203 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->draw_round_rect(x-10.f, y-10.f, w, h, 17.0f); + RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 17.0f); Graphics()->QuadsEnd(); // render title - if(!title) + if(!pTitle) { - if(gameclient.snap.gameobj->game_over) - title = localize("Game over"); + if(m_pClient->m_Snap.m_pGameobj->m_GameOver) + pTitle = Localize("Game over"); else - title = localize("Score board"); + pTitle = Localize("Score board"); } - float tw = gfx_text_width(0, 48, title, -1); + float tw = TextRender()->TextWidth(0, 48, pTitle, -1); - if(team == -1) + if(Team == -1) { - gfx_text(0, x+w/2-tw/2, y, 48, title, -1); + TextRender()->Text(0, x+w/2-tw/2, y, 48, pTitle, -1); } else { - gfx_text(0, x+10, y, 48, title, -1); + TextRender()->Text(0, x+10, y, 48, pTitle, -1); - if(gameclient.snap.gameobj) + if(m_pClient->m_Snap.m_pGameobj) { - char buf[128]; - int score = team ? gameclient.snap.gameobj->teamscore_blue : gameclient.snap.gameobj->teamscore_red; - str_format(buf, sizeof(buf), "%d", score); - tw = gfx_text_width(0, 48, buf, -1); - gfx_text(0, x+w-tw-30, y, 48, buf, -1); + char aBuf[128]; + int Score = Team ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue : m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed; + str_format(aBuf, sizeof(aBuf), "%d", Score); + tw = TextRender()->TextWidth(0, 48, aBuf, -1); + TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1); } } y += 54.0f; // find players - const NETOBJ_PLAYER_INFO *players[MAX_CLIENTS] = {0}; - int num_players = 0; - for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) + const CNetObj_PlayerInfo *paPlayers[MAX_CLIENTS] = {0}; + int NumPlayers = 0; + for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - if(item.type == NETOBJTYPE_PLAYER_INFO) + if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { - const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data; - if(info->team == team) + const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; + if(pInfo->m_Team == Team) { - players[num_players] = info; - num_players++; + paPlayers[NumPlayers] = pInfo; + NumPlayers++; } } } // sort players - for(int k = 0; k < num_players; k++) // ffs, bubblesort + for(int k = 0; k < NumPlayers; k++) // ffs, bubblesort { - for(int i = 0; i < num_players-k-1; i++) + for(int i = 0; i < NumPlayers-k-1; i++) { - if(players[i]->score < players[i+1]->score) + if(paPlayers[i]->m_Score < paPlayers[i+1]->m_Score) { - const NETOBJ_PLAYER_INFO *tmp = players[i]; - players[i] = players[i+1]; - players[i+1] = tmp; + const CNetObj_PlayerInfo *pTmp = paPlayers[i]; + paPlayers[i] = paPlayers[i+1]; + paPlayers[i+1] = pTmp; } } } // render headlines - gfx_text(0, x+10, y, 24.0f, localize("Score"), -1); - gfx_text(0, x+125, y, 24.0f, localize("Name"), -1); - gfx_text(0, x+w-70, y, 24.0f, localize("Ping"), -1); + TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1); + TextRender()->Text(0, x+125, y, 24.0f, Localize("Name"), -1); + TextRender()->Text(0, x+w-70, y, 24.0f, Localize("Ping"), -1); y += 29.0f; - float font_size = 35.0f; - float line_height = 50.0f; - float tee_sizemod = 1.0f; - float tee_offset = 0.0f; + float FontSize = 35.0f; + float LineHeight = 50.0f; + float TeeSizeMod = 1.0f; + float TeeOffset = 0.0f; - if(num_players > 13) + if(NumPlayers > 13) { - font_size = 30.0f; - line_height = 40.0f; - tee_sizemod = 0.8f; - tee_offset = -5.0f; + FontSize = 30.0f; + LineHeight = 40.0f; + TeeSizeMod = 0.8f; + TeeOffset = -5.0f; } // render player scores - for(int i = 0; i < num_players; i++) + for(int i = 0; i < NumPlayers; i++) { - const NETOBJ_PLAYER_INFO *info = players[i]; + const CNetObj_PlayerInfo *pInfo = paPlayers[i]; // make sure that we render the correct team - char buf[128]; - if(info->local) + char aBuf[128]; + if(pInfo->m_Local) { // background so it's easy to find the local player Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,0.25f); - RenderTools()->draw_round_rect(x, y, w-20, line_height*0.95f, 17.0f); + RenderTools()->DrawRoundRect(x, y, w-20, LineHeight*0.95f, 17.0f); Graphics()->QuadsEnd(); } - str_format(buf, sizeof(buf), "%4d", info->score); - gfx_text(0, x+60-gfx_text_width(0, font_size,buf,-1), y, font_size, buf, -1); + str_format(aBuf, sizeof(aBuf), "%4d", pInfo->m_Score); + TextRender()->Text(0, x+60-TextRender()->TextWidth(0, FontSize,aBuf,-1), y, FontSize, aBuf, -1); - gfx_text(0, x+128, y, font_size, gameclient.clients[info->cid].name, -1); + TextRender()->Text(0, x+128, y, FontSize, m_pClient->m_aClients[pInfo->m_ClientId].m_aName, -1); - str_format(buf, sizeof(buf), "%4d", info->latency); - float tw = gfx_text_width(0, font_size, buf, -1); - gfx_text(0, x+w-tw-35, y, font_size, buf, -1); + str_format(aBuf, sizeof(aBuf), "%4d", pInfo->m_Latency); + float tw = TextRender()->TextWidth(0, FontSize, aBuf, -1); + TextRender()->Text(0, x+w-tw-35, y, FontSize, aBuf, -1); // render avatar - if((gameclient.snap.flags[0] && gameclient.snap.flags[0]->carried_by == info->cid) || - (gameclient.snap.flags[1] && gameclient.snap.flags[1]->carried_by == info->cid)) + if((m_pClient->m_Snap.m_paFlags[0] && m_pClient->m_Snap.m_paFlags[0]->m_CarriedBy == pInfo->m_ClientId) || + (m_pClient->m_Snap.m_paFlags[1] && m_pClient->m_Snap.m_paFlags[1]->m_CarriedBy == pInfo->m_ClientId)) { Graphics()->BlendNormal(); - Graphics()->TextureSet(data->images[IMAGE_GAME].id); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - if(info->team == 0) RenderTools()->select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); - else RenderTools()->select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); + if(pInfo->m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); + else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); float size = 64.0f; - Graphics()->QuadsDrawTL(x+55, y-15, size/2, size); + IGraphics::CQuadItem QuadItem(x+55, y-15, size/2, size); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } - TEE_RENDER_INFO teeinfo = gameclient.clients[info->cid].render_info; - teeinfo.size *= tee_sizemod; - RenderTools()->RenderTee(ANIMSTATE::get_idle(), &teeinfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+tee_offset)); + CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientId].m_RenderInfo; + TeeInfo.m_Size *= TeeSizeMod; + RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+TeeOffset)); - y += line_height; + y += LineHeight; } } -void SCOREBOARD::on_render() +void CScoreboard::OnRender() { - bool do_scoreboard = false; + bool DoScoreBoard = false; // if we activly wanna look on the scoreboard - if(active) - do_scoreboard = true; + if(m_Active) + DoScoreBoard = true; - if(gameclient.snap.local_info && gameclient.snap.local_info->team != -1) + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != -1) { // we are not a spectator, check if we are ead - if(!gameclient.snap.local_character || gameclient.snap.local_character->health < 0) - do_scoreboard = true; + if(!m_pClient->m_Snap.m_pLocalCharacter || m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) + DoScoreBoard = true; } // if we the game is over - if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) - do_scoreboard = true; + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) + DoScoreBoard = true; - if(!do_scoreboard) + if(!DoScoreBoard) return; // if the score board is active, then we should clear the motd message aswell - if(active) - gameclient.motd->clear(); + if(m_Active) + m_pClient->m_pMotd->Clear(); - float width = 400*3.0f*Graphics()->ScreenAspect(); - float height = 400*3.0f; + float Width = 400*3.0f*Graphics()->ScreenAspect(); + float Height = 400*3.0f; - Graphics()->MapScreen(0, 0, width, height); + Graphics()->MapScreen(0, 0, Width, Height); float w = 650.0f; - if(gameclient.snap.gameobj && !(gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS)) + if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)) { - render_scoreboard(width/2-w/2, 150.0f, w, 0, 0); + RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0); //render_scoreboard(gameobj, 0, 0, -1, 0); } else { - if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) { - const char *text = localize("Draw!"); - if(gameclient.snap.gameobj->teamscore_red > gameclient.snap.gameobj->teamscore_blue) - text = localize("Red team wins!"); - else if(gameclient.snap.gameobj->teamscore_blue > gameclient.snap.gameobj->teamscore_red) - text = localize("Blue team wins!"); + const char *pText = Localize("Draw!"); + if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed > m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue) + pText = Localize("Red team wins!"); + else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed) + pText = Localize("Blue team wins!"); - float w = gfx_text_width(0, 92.0f, text, -1); - gfx_text(0, width/2-w/2, 45, 92.0f, text, -1); + float w = TextRender()->TextWidth(0, 92.0f, pText, -1); + TextRender()->Text(0, Width/2-w/2, 45, 92.0f, pText, -1); } - render_scoreboard(width/2-w-20, 150.0f, w, 0, localize("Red team")); - render_scoreboard(width/2 + 20, 150.0f, w, 1, localize("Blue team")); + RenderScoreboard(Width/2-w-20, 150.0f, w, 0, Localize("Red team")); + RenderScoreboard(Width/2 + 20, 150.0f, w, 1, Localize("Blue team")); } - render_goals(width/2-w/2, 150+750+25, w); - render_spectators(width/2-w/2, 150+750+25+50+25, w); + RenderGoals(Width/2-w/2, 150+750+25, w); + RenderSpectators(Width/2-w/2, 150+750+25+50+25, w); } diff --git a/src/game/client/components/scoreboard.h b/src/game/client/components/scoreboard.h new file mode 100644 index 00000000..5aa2f0a7 --- /dev/null +++ b/src/game/client/components/scoreboard.h @@ -0,0 +1,22 @@ +#ifndef GAME_CLIENT_COMPONENTS_SCOREBOARD_H +#define GAME_CLIENT_COMPONENTS_SCOREBOARD_H +#include <game/client/component.h> + +class CScoreboard : public CComponent +{ + void RenderGoals(float x, float y, float w); + void RenderSpectators(float x, float y, float w); + void RenderScoreboard(float x, float y, float w, int Team, const char *pTitle); + + static void ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData); + + bool m_Active; + +public: + CScoreboard(); + virtual void OnReset(); + virtual void OnConsoleInit(); + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/components/scoreboard.hpp b/src/game/client/components/scoreboard.hpp deleted file mode 100644 index 222dab9d..00000000 --- a/src/game/client/components/scoreboard.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <game/client/component.hpp> - -class SCOREBOARD : public COMPONENT -{ - void render_goals(float x, float y, float w); - void render_spectators(float x, float y, float w); - void render_scoreboard(float x, float y, float w, int team, const char *title); - - static void con_key_scoreboard(void *result, void *user_data); - - bool active; - -public: - SCOREBOARD(); - virtual void on_reset(); - virtual void on_console_init(); - virtual void on_render(); -}; - diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index ad3607a1..582adb10 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -1,153 +1,150 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <string.h> -#include <stdio.h> +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <math.h> #include <base/system.h> -#include <base/math.hpp> +#include <base/math.h> -#include <engine/client/graphics.h> -#include <engine/e_client_interface.h> +#include <engine/graphics.h> +#include <engine/storage.h> +#include <engine/shared/engine.h> -#include <engine/e_engine.h> +#include "skins.h" -#include "skins.hpp" - -SKINS::SKINS() +CSkins::CSkins() { - num_skins = 0; + m_NumSkins = 0; } -void SKINS::skinscan(const char *name, int is_dir, void *user) +void CSkins::SkinScan(const char *pName, int IsDir, void *pUser) { - SKINS *self = (SKINS *)user; - int l = strlen(name); - if(l < 4 || is_dir || self->num_skins == MAX_SKINS) + CSkins *pSelf = (CSkins *)pUser; + int l = str_length(pName); + if(l < 4 || IsDir || pSelf->m_NumSkins == MAX_SKINS) return; - if(strcmp(name+l-4, ".png") != 0) + if(str_comp(pName+l-4, ".png") != 0) return; - char buf[512]; - str_format(buf, sizeof(buf), "skins/%s", name); - IMAGE_INFO info; - if(!self->Graphics()->LoadPNG(&info, buf)) + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "skins/%s", pName); + CImageInfo Info; + if(!pSelf->Graphics()->LoadPNG(&Info, aBuf)) { - dbg_msg("game", "failed to load skin from %s", name); + dbg_msg("game", "failed to load skin from %s", pName); return; } - self->skins[self->num_skins].org_texture = self->Graphics()->LoadTextureRaw(info.width, info.height, info.format, info.data, info.format, 0); + pSelf->m_aSkins[pSelf->m_NumSkins].m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); - int body_size = 96; // body size - unsigned char *d = (unsigned char *)info.data; - int pitch = info.width*4; + int BodySize = 96; // body size + unsigned char *d = (unsigned char *)Info.m_pData; + int Pitch = Info.m_Width*4; // dig out blood color { - int colors[3] = {0}; - for(int y = 0; y < body_size; y++) - for(int x = 0; x < body_size; x++) + int aColors[3] = {0}; + for(int y = 0; y < BodySize; y++) + for(int x = 0; x < BodySize; x++) { - if(d[y*pitch+x*4+3] > 128) + if(d[y*Pitch+x*4+3] > 128) { - colors[0] += d[y*pitch+x*4+0]; - colors[1] += d[y*pitch+x*4+1]; - colors[2] += d[y*pitch+x*4+2]; + aColors[0] += d[y*Pitch+x*4+0]; + aColors[1] += d[y*Pitch+x*4+1]; + aColors[2] += d[y*Pitch+x*4+2]; } } - self->skins[self->num_skins].blood_color = normalize(vec3(colors[0], colors[1], colors[2])); + pSelf->m_aSkins[pSelf->m_NumSkins].m_BloodColor = normalize(vec3(aColors[0], aColors[1], aColors[2])); } // create colorless version - int step = info.format == IMG_RGBA ? 4 : 3; + int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3; // make the texture gray scale - for(int i = 0; i < info.width*info.height; i++) + for(int i = 0; i < Info.m_Width*Info.m_Height; i++) { - int v = (d[i*step]+d[i*step+1]+d[i*step+2])/3; - d[i*step] = v; - d[i*step+1] = v; - d[i*step+2] = v; + int v = (d[i*Step]+d[i*Step+1]+d[i*Step+2])/3; + d[i*Step] = v; + d[i*Step+1] = v; + d[i*Step+2] = v; } if(1) { - int freq[256] = {0}; - int org_weight = 0; - int new_weight = 192; + int Freq[256] = {0}; + int OrgWeight = 0; + int NewWeight = 192; // find most common frequence - for(int y = 0; y < body_size; y++) - for(int x = 0; x < body_size; x++) + for(int y = 0; y < BodySize; y++) + for(int x = 0; x < BodySize; x++) { - if(d[y*pitch+x*4+3] > 128) - freq[d[y*pitch+x*4]]++; + if(d[y*Pitch+x*4+3] > 128) + Freq[d[y*Pitch+x*4]]++; } for(int i = 1; i < 256; i++) { - if(freq[org_weight] < freq[i]) - org_weight = i; + if(Freq[OrgWeight] < Freq[i]) + OrgWeight = i; } // reorder - int inv_org_weight = 255-org_weight; - int inv_new_weight = 255-new_weight; - for(int y = 0; y < body_size; y++) - for(int x = 0; x < body_size; x++) + int InvOrgWeight = 255-OrgWeight; + int InvNewWeight = 255-NewWeight; + for(int y = 0; y < BodySize; y++) + for(int x = 0; x < BodySize; x++) { - int v = d[y*pitch+x*4]; - if(v <= org_weight) - v = (int)(((v/(float)org_weight) * new_weight)); + int v = d[y*Pitch+x*4]; + if(v <= OrgWeight) + v = (int)(((v/(float)OrgWeight) * NewWeight)); else - v = (int)(((v-org_weight)/(float)inv_org_weight)*inv_new_weight + new_weight); - d[y*pitch+x*4] = v; - d[y*pitch+x*4+1] = v; - d[y*pitch+x*4+2] = v; + v = (int)(((v-OrgWeight)/(float)InvOrgWeight)*InvNewWeight + NewWeight); + d[y*Pitch+x*4] = v; + d[y*Pitch+x*4+1] = v; + d[y*Pitch+x*4+2] = v; } } - self->skins[self->num_skins].color_texture = self->Graphics()->LoadTextureRaw(info.width, info.height, info.format, info.data, info.format, 0); - mem_free(info.data); + pSelf->m_aSkins[pSelf->m_NumSkins].m_ColorTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); + mem_free(Info.m_pData); // set skin data - strncpy(self->skins[self->num_skins].name, name, min((int)sizeof(self->skins[self->num_skins].name),l-4)); - dbg_msg("game", "load skin %s", self->skins[self->num_skins].name); - self->num_skins++; + str_copy(pSelf->m_aSkins[pSelf->m_NumSkins].m_aName, pName, min((int)sizeof(pSelf->m_aSkins[pSelf->m_NumSkins].m_aName),l-3)); + dbg_msg("game", "load skin %s", pSelf->m_aSkins[pSelf->m_NumSkins].m_aName); + pSelf->m_NumSkins++; } -void SKINS::init() +void CSkins::Init() { // load skins - num_skins = 0; - engine_listdir(LISTDIRTYPE_ALL, "skins", skinscan, this); + m_NumSkins = 0; + Storage()->ListDirectory(IStorage::TYPE_ALL, "skins", SkinScan, this); } -int SKINS::num() +int CSkins::Num() { - return num_skins; + return m_NumSkins; } -const SKINS::SKIN *SKINS::get(int index) +const CSkins::CSkin *CSkins::Get(int Index) { - return &skins[index%num_skins]; + return &m_aSkins[Index%m_NumSkins]; } -int SKINS::find(const char *name) +int CSkins::Find(const char *pName) { - for(int i = 0; i < num_skins; i++) + for(int i = 0; i < m_NumSkins; i++) { - if(strcmp(skins[i].name, name) == 0) + if(str_comp(m_aSkins[i].m_aName, pName) == 0) return i; } return -1; } // these converter functions were nicked from some random internet pages -static float hue_to_rgb(float v1, float v2, float h) +static float HueToRgb(float v1, float v2, float h) { if(h < 0) h += 1; if(h > 1) h -= 1; @@ -157,16 +154,16 @@ static float hue_to_rgb(float v1, float v2, float h) return v1; } -static vec3 hsl_to_rgb(vec3 in) +static vec3 HslToRgb(vec3 in) { float v1, v2; - vec3 out; + vec3 Out; if(in.s == 0) { - out.r = in.l; - out.g = in.l; - out.b = in.l; + Out.r = in.l; + Out.g = in.l; + Out.b = in.l; } else { @@ -177,16 +174,16 @@ static vec3 hsl_to_rgb(vec3 in) v1 = 2 * in.l - v2; - out.r = hue_to_rgb(v1, v2, in.h + (1.0f/3.0f)); - out.g = hue_to_rgb(v1, v2, in.h); - out.b = hue_to_rgb(v1, v2, in.h - (1.0f/3.0f)); + Out.r = HueToRgb(v1, v2, in.h + (1.0f/3.0f)); + Out.g = HueToRgb(v1, v2, in.h); + Out.b = HueToRgb(v1, v2, in.h - (1.0f/3.0f)); } - return out; + return Out; } -vec4 SKINS::get_color(int v) +vec4 CSkins::GetColor(int v) { - vec3 r = hsl_to_rgb(vec3((v>>16)/255.0f, ((v>>8)&0xff)/255.0f, 0.5f+(v&0xff)/255.0f*0.5f)); + vec3 r = HslToRgb(vec3(((v>>16)&0xff)/255.0f, ((v>>8)&0xff)/255.0f, 0.5f+(v&0xff)/255.0f*0.5f)); return vec4(r.r, r.g, r.b, 1.0f); } diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h new file mode 100644 index 00000000..f733140f --- /dev/null +++ b/src/game/client/components/skins.h @@ -0,0 +1,39 @@ +#ifndef GAME_CLIENT_COMPONENTS_SKINS_H +#define GAME_CLIENT_COMPONENTS_SKINS_H +#include <base/vmath.h> +#include <game/client/component.h> + +class CSkins : public CComponent +{ +public: + // do this better and nicer + struct CSkin + { + int m_OrgTexture; + int m_ColorTexture; + char m_aName[31]; + char m_aTerm[1]; + vec3 m_BloodColor; + } ; + + CSkins(); + + void Init(); + + vec4 GetColor(int v); + int Num(); + const CSkin *Get(int Index); + int Find(const char *pName); + +private: + enum + { + MAX_SKINS=256, + }; + + CSkin m_aSkins[MAX_SKINS]; + int m_NumSkins; + + static void SkinScan(const char *pName, int IsDir, void *pUser); +}; +#endif diff --git a/src/game/client/components/skins.hpp b/src/game/client/components/skins.hpp deleted file mode 100644 index 078fd71d..00000000 --- a/src/game/client/components/skins.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#include <base/vmath.hpp> -#include <game/client/component.hpp> - -class SKINS : public COMPONENT -{ -public: - // do this better and nicer - typedef struct - { - int org_texture; - int color_texture; - char name[31]; - char term[1]; - vec3 blood_color; - } SKIN; - - SKINS(); - - void init(); - - vec4 get_color(int v); - int num(); - const SKIN *get(int index); - int find(const char *name); - -private: - enum - { - MAX_SKINS=256, - }; - - SKIN skins[MAX_SKINS]; - int num_skins; - - static void skinscan(const char *name, int is_dir, void *user); -}; diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index dfa7e31b..84e45efa 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -1,54 +1,91 @@ -#include <engine/e_client_interface.h> -#include <game/generated/gc_data.hpp> -#include <game/client/gameclient.hpp> -#include <game/client/components/camera.hpp> -#include "sounds.hpp" +#include <engine/sound.h> +#include <game/generated/client_data.h> +#include <game/client/gameclient.h> +#include <game/client/components/camera.h> +#include "sounds.h" -void SOUNDS::on_init() +void CSounds::OnInit() { // setup sound channels - snd_set_channel(SOUNDS::CHN_GUI, 1.0f, 0.0f); - snd_set_channel(SOUNDS::CHN_MUSIC, 1.0f, 0.0f); - snd_set_channel(SOUNDS::CHN_WORLD, 0.9f, 1.0f); - snd_set_channel(SOUNDS::CHN_GLOBAL, 1.0f, 0.0f); + Sound()->SetChannel(CSounds::CHN_GUI, 1.0f, 0.0f); + Sound()->SetChannel(CSounds::CHN_MUSIC, 1.0f, 0.0f); + Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f, 1.0f); + Sound()->SetChannel(CSounds::CHN_GLOBAL, 1.0f, 0.0f); - snd_set_listener_pos(0.0f, 0.0f); + Sound()->SetListenerPos(0.0f, 0.0f); + + ClearQueue(); +} + +void CSounds::OnReset() +{ + Sound()->StopAll(); + ClearQueue(); } -void SOUNDS::on_render() +void CSounds::OnRender() { // set listner pos - snd_set_listener_pos(gameclient.camera->center.x, gameclient.camera->center.y); + Sound()->SetListenerPos(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y); + + // play sound from queue + if(m_QueuePos > 0) + { + int64 Now = time_get(); + if(m_QueueWaitTime <= Now) + { + Play(CHN_GLOBAL, m_aQueue[0], 1.0f, vec2(0,0)); + m_QueueWaitTime = Now+time_freq()*3/10; // wait 300ms before playing the next one + if(--m_QueuePos > 0) + mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(int)); + } + } } -void SOUNDS::play_and_record(int chn, int setid, float vol, vec2 pos) +void CSounds::ClearQueue() { - NETMSG_SV_SOUNDGLOBAL msg; - msg.soundid = setid; - msg.pack(MSGFLAG_NOSEND|MSGFLAG_RECORD); - client_send_msg(); + mem_zero(m_aQueue, sizeof(m_aQueue)); + m_QueuePos = 0; + m_QueueWaitTime = time_get(); +} + +void CSounds::Enqueue(int SetId) +{ + // add sound to the queue + if(m_QueuePos < QUEUE_SIZE) + m_aQueue[m_QueuePos++] = SetId; +} + +void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos) +{ + CNetMsg_Sv_SoundGlobal Msg; + Msg.m_Soundid = SetId; + Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); - play(chn, setid, vol, pos); + Play(Chn, SetId, Vol, Pos); } -void SOUNDS::play(int chn, int setid, float vol, vec2 pos) +void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos) { - SOUNDSET *set = &data->sounds[setid]; + if(SetId < 0 || SetId >= g_pData->m_NumSounds) + return; + + SOUNDSET *pSet = &g_pData->m_aSounds[SetId]; - if(!set->num_sounds) + if(!pSet->m_NumSounds) return; - if(set->num_sounds == 1) + if(pSet->m_NumSounds == 1) { - snd_play_at(chn, set->sounds[0].id, 0, pos.x, pos.y); + Sound()->PlayAt(Chn, pSet->m_aSounds[0].m_Id, 0, Pos.x, Pos.y); return; } // play a random one int id; do { - id = rand() % set->num_sounds; - } while(id == set->last); - snd_play_at(chn, set->sounds[id].id, 0, pos.x, pos.y); - set->last = id; + id = rand() % pSet->m_NumSounds; + } while(id == pSet->m_Last); + Sound()->PlayAt(Chn, pSet->m_aSounds[id].m_Id, 0, Pos.x, Pos.y); + pSet->m_Last = id; } diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h new file mode 100644 index 00000000..ce74b85e --- /dev/null +++ b/src/game/client/components/sounds.h @@ -0,0 +1,36 @@ +#ifndef GAME_CLIENT_COMPONENTS_SOUNDS_H +#define GAME_CLIENT_COMPONENTS_SOUNDS_H +#include <game/client/component.h> + +class CSounds : public CComponent +{ + enum + { + QUEUE_SIZE = 32, + }; + int m_aQueue[QUEUE_SIZE]; + int m_QueuePos; + int64 m_QueueWaitTime; + +public: + // sound channels + enum + { + CHN_GUI=0, + CHN_MUSIC, + CHN_WORLD, + CHN_GLOBAL, + }; + + virtual void OnInit(); + virtual void OnReset(); + virtual void OnRender(); + + void ClearQueue(); + void Enqueue(int SetId); + void Play(int Channel, int SetId, float Vol, vec2 Pos); + void PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos); +}; + + +#endif diff --git a/src/game/client/components/sounds.hpp b/src/game/client/components/sounds.hpp deleted file mode 100644 index 95ddb1ec..00000000 --- a/src/game/client/components/sounds.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#include <game/client/component.hpp> - -class SOUNDS : public COMPONENT -{ -public: - // sound channels - enum - { - CHN_GUI=0, - CHN_MUSIC, - CHN_WORLD, - CHN_GLOBAL, - }; - - virtual void on_init(); - virtual void on_render(); - - void play(int chn, int setid, float vol, vec2 pos); - void play_and_record(int chn, int setid, float vol, vec2 pos); -}; - - diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index dcf5c954..17c0fe31 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -1,200 +1,219 @@ -#include <engine/e_client_interface.h> -#include <game/generated/g_protocol.hpp> -#include <base/vmath.hpp> -#include <game/client/render.hpp> -//#include <game/client/gameclient.hpp> -#include "voting.hpp" - -void VOTING::con_callvote(void *result, void *user_data) +#include <engine/shared/config.h> + +#include <game/generated/protocol.h> +#include <base/vmath.h> +#include <game/client/render.h> +//#include <game/client/gameclient.h> +#include "voting.h" + +void CVoting::ConCallvote(IConsole::IResult *pResult, void *pUserData) +{ + CVoting *pSelf = (CVoting*)pUserData; + pSelf->Callvote(pResult->GetString(0), pResult->GetString(1)); +} + +void CVoting::ConVote(IConsole::IResult *pResult, void *pUserData) +{ + CVoting *pSelf = (CVoting *)pUserData; + if(str_comp_nocase(pResult->GetString(0), "yes") == 0) + pSelf->Vote(1); + else if(str_comp_nocase(pResult->GetString(0), "no") == 0) + pSelf->Vote(-1); +} + +void CVoting::Callvote(const char *pType, const char *pValue) { - VOTING *self = (VOTING*)user_data; - self->callvote(console_arg_string(result, 0), console_arg_string(result, 1)); + CNetMsg_Cl_CallVote Msg = {0}; + Msg.m_Type = pType; + Msg.m_Value = pValue; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } -void VOTING::con_vote(void *result, void *user_data) +void CVoting::CallvoteKick(int ClientId) { - VOTING *self = (VOTING *)user_data; - if(str_comp_nocase(console_arg_string(result, 0), "yes") == 0) - self->vote(1); - else if(str_comp_nocase(console_arg_string(result, 0), "no") == 0) - self->vote(-1); + char Buf[32]; + str_format(Buf, sizeof(Buf), "%d", ClientId); + Callvote("kick", Buf); } -void VOTING::callvote(const char *type, const char *value) +void CVoting::CallvoteOption(int OptionId) { - NETMSG_CL_CALLVOTE msg = {0}; - msg.type = type; - msg.value = value; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CVoteOption *pOption = m_pFirst; + while(pOption && OptionId >= 0) + { + if(OptionId == 0) + { + Callvote("option", pOption->m_aCommand); + break; + } + + OptionId--; + pOption = pOption->m_pNext; + } } -void VOTING::callvote_kick(int client_id) +void CVoting::ForcevoteKick(int ClientId) { - char buf[32]; - str_format(buf, sizeof(buf), "%d", client_id); - callvote("kick", buf); + char Buf[32]; + str_format(Buf, sizeof(Buf), "kick %d", ClientId); + Client()->Rcon(Buf); } -void VOTING::callvote_option(int option_id) +void CVoting::ForcevoteOption(int OptionId) { - VOTEOPTION *option = this->first; - while(option && option_id >= 0) + CVoteOption *pOption = m_pFirst; + while(pOption && OptionId >= 0) { - if(option_id == 0) + if(OptionId == 0) { - callvote("option", option->command); + Client()->Rcon(pOption->m_aCommand); break; } - option_id--; - option = option->next; + OptionId--; + pOption = pOption->m_pNext; } } -void VOTING::vote(int v) +void CVoting::Vote(int v) { - NETMSG_CL_VOTE msg = {v}; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_Vote Msg = {v}; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } -VOTING::VOTING() +CVoting::CVoting() { - heap = 0; - clearoptions(); - on_reset(); + ClearOptions(); + OnReset(); } -void VOTING::clearoptions() +void CVoting::ClearOptions() { - if(heap) - memheap_destroy(heap); - heap = memheap_create(); + m_Heap.Reset(); - first = 0; - last = 0; + m_pFirst = 0; + m_pLast = 0; } -void VOTING::on_reset() +void CVoting::OnReset() { - closetime = 0; - description[0] = 0; - command[0] = 0; - yes = no = pass = total = 0; - voted = 0; + m_Closetime = 0; + m_aDescription[0] = 0; + m_aCommand[0] = 0; + m_Yes = m_No = m_Pass = m_Total = 0; + m_Voted = 0; } -void VOTING::on_console_init() +void CVoting::OnConsoleInit() { - MACRO_REGISTER_COMMAND("callvote", "sr", CFGFLAG_CLIENT, con_callvote, this, "Call vote"); - MACRO_REGISTER_COMMAND("vote", "r", CFGFLAG_CLIENT, con_vote, this, "Vote yes/no"); + Console()->Register("callvote", "sr", CFGFLAG_CLIENT, ConCallvote, this, "Call vote"); + Console()->Register("vote", "r", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no"); } -void VOTING::on_message(int msgtype, void *rawmsg) +void CVoting::OnMessage(int MsgType, void *pRawMsg) { - if(msgtype == NETMSGTYPE_SV_VOTE_SET) + if(MsgType == NETMSGTYPE_SV_VOTESET) { - NETMSG_SV_VOTE_SET *msg = (NETMSG_SV_VOTE_SET *)rawmsg; - if(msg->timeout) + CNetMsg_Sv_VoteSet *pMsg = (CNetMsg_Sv_VoteSet *)pRawMsg; + if(pMsg->m_Timeout) { - on_reset(); - str_copy(description, msg->description, sizeof(description)); - str_copy(command, msg->command, sizeof(description)); - closetime = time_get() + time_freq() * msg->timeout; + OnReset(); + str_copy(m_aDescription, pMsg->m_pDescription, sizeof(m_aDescription)); + str_copy(m_aCommand, pMsg->m_pCommand, sizeof(m_aCommand)); + m_Closetime = time_get() + time_freq() * pMsg->m_Timeout; } else - on_reset(); + OnReset(); } - else if(msgtype == NETMSGTYPE_SV_VOTE_STATUS) + else if(MsgType == NETMSGTYPE_SV_VOTESTATUS) { - NETMSG_SV_VOTE_STATUS *msg = (NETMSG_SV_VOTE_STATUS *)rawmsg; - yes = msg->yes; - no = msg->no; - pass = msg->pass; - total = msg->total; + CNetMsg_Sv_VoteStatus *pMsg = (CNetMsg_Sv_VoteStatus *)pRawMsg; + m_Yes = pMsg->m_Yes; + m_No = pMsg->m_No; + m_Pass = pMsg->m_Pass; + m_Total = pMsg->m_Total; } - else if(msgtype == NETMSGTYPE_SV_VOTE_CLEAROPTIONS) + else if(MsgType == NETMSGTYPE_SV_VOTECLEAROPTIONS) { - clearoptions(); + ClearOptions(); } - else if(msgtype == NETMSGTYPE_SV_VOTE_OPTION) + else if(MsgType == NETMSGTYPE_SV_VOTEOPTION) { - NETMSG_SV_VOTE_OPTION *msg = (NETMSG_SV_VOTE_OPTION *)rawmsg; - int len = str_length(msg->command); + CNetMsg_Sv_VoteOption *pMsg = (CNetMsg_Sv_VoteOption *)pRawMsg; + int Len = str_length(pMsg->m_pCommand); - VOTEOPTION *option = (VOTEOPTION *)memheap_allocate(heap, sizeof(VOTEOPTION) + len); - option->next = 0; - option->prev = last; - if(option->prev) - option->prev->next = option; - last = option; - if(!first) - first = option; + CVoteOption *pOption = (CVoteOption *)m_Heap.Allocate(sizeof(CVoteOption) + Len); + pOption->m_pNext = 0; + pOption->m_pPrev = m_pLast; + if(pOption->m_pPrev) + pOption->m_pPrev->m_pNext = pOption; + m_pLast = pOption; + if(!m_pFirst) + m_pFirst = pOption; - mem_copy(option->command, msg->command, len+1); + mem_copy(pOption->m_aCommand, pMsg->m_pCommand, Len+1); } } -void VOTING::on_render() +void CVoting::OnRender() { } -void VOTING::render_bars(CUIRect bars, bool text) +void CVoting::RenderBars(CUIRect Bars, bool Text) { - RenderTools()->DrawUIRect(&bars, vec4(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, bars.h/3); + RenderTools()->DrawUIRect(&Bars, vec4(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, Bars.h/3); - CUIRect splitter = bars; - splitter.x = splitter.x+splitter.w/2; - splitter.w = splitter.h/2.0f; - splitter.x -= splitter.w/2; - RenderTools()->DrawUIRect(&splitter, vec4(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, splitter.h/4); + CUIRect Splitter = Bars; + Splitter.x = Splitter.x+Splitter.w/2; + Splitter.w = Splitter.h/2.0f; + Splitter.x -= Splitter.w/2; + RenderTools()->DrawUIRect(&Splitter, vec4(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, Splitter.h/4); - if(total) + if(m_Total) { - CUIRect pass_area = bars; - if(yes) + CUIRect PassArea = Bars; + if(m_Yes) { - CUIRect yes_area = bars; - yes_area.w *= yes/(float)total; - RenderTools()->DrawUIRect(&yes_area, vec4(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, bars.h/3); + CUIRect YesArea = Bars; + YesArea.w *= m_Yes/(float)m_Total; + RenderTools()->DrawUIRect(&YesArea, vec4(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3); - if(text) + if(Text) { - char buf[256]; - str_format(buf, sizeof(buf), "%d", yes); - UI()->DoLabel(&yes_area, buf, bars.h*0.75f, 0); + char Buf[256]; + str_format(Buf, sizeof(Buf), "%d", m_Yes); + UI()->DoLabel(&YesArea, Buf, Bars.h*0.75f, 0); } - pass_area.x += yes_area.w; - pass_area.w -= yes_area.w; + PassArea.x += YesArea.w; + PassArea.w -= YesArea.w; } - if(no) + if(m_No) { - CUIRect no_area = bars; - no_area.w *= no/(float)total; - no_area.x = (bars.x + bars.w)-no_area.w; - RenderTools()->DrawUIRect(&no_area, vec4(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, bars.h/3); + CUIRect NoArea = Bars; + NoArea.w *= m_No/(float)m_Total; + NoArea.x = (Bars.x + Bars.w)-NoArea.w; + RenderTools()->DrawUIRect(&NoArea, vec4(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3); - if(text) + if(Text) { - char buf[256]; - str_format(buf, sizeof(buf), "%d", no); - UI()->DoLabel(&no_area, buf, bars.h*0.75f, 0); + char Buf[256]; + str_format(Buf, sizeof(Buf), "%d", m_No); + UI()->DoLabel(&NoArea, Buf, Bars.h*0.75f, 0); } - pass_area.w -= no_area.w; + PassArea.w -= NoArea.w; } - if(text && pass) + if(Text && m_Pass) { - char buf[256]; - str_format(buf, sizeof(buf), "%d", pass); - UI()->DoLabel(&pass_area, buf, bars.h*0.75f, 0); + char Buf[256]; + str_format(Buf, sizeof(Buf), "%d", m_Pass); + UI()->DoLabel(&PassArea, Buf, Bars.h*0.75f, 0); } } } diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h new file mode 100644 index 00000000..1f5d2fc5 --- /dev/null +++ b/src/game/client/components/voting.h @@ -0,0 +1,58 @@ +#ifndef GAME_CLIENT_COMPONENTS_VOTING_H +#define GAME_CLIENT_COMPONENTS_VOTING_H +#include <game/client/component.h> +#include <game/client/ui.h> +#include <engine/shared/memheap.h> + +class CVoting : public CComponent +{ + CHeap m_Heap; + + static void ConCallvote(IConsole::IResult *pResult, void *pUserData); + static void ConVote(IConsole::IResult *pResult, void *pUserData); + + int64 m_Closetime; + char m_aDescription[512]; + char m_aCommand[512]; + int m_Voted; + + void ClearOptions(); + void Callvote(const char *pType, const char *pValue); + +public: + + struct CVoteOption + { + CVoteOption *m_pNext; + CVoteOption *m_pPrev; + char m_aCommand[1]; + }; + + CVoteOption *m_pFirst; + CVoteOption *m_pLast; + + CVoting(); + virtual void OnReset(); + virtual void OnConsoleInit(); + virtual void OnMessage(int Msgtype, void *pRawMsg); + virtual void OnRender(); + + void RenderBars(CUIRect Bars, bool Text); + + void CallvoteKick(int ClientId); + void CallvoteOption(int Option); + void ForcevoteKick(int ClientId); + void ForcevoteOption(int Option); + + void Vote(int v); // -1 = no, 1 = yes + + int SecondsLeft() { return (m_Closetime - time_get())/time_freq(); } + bool IsVoting() { return m_Closetime != 0; } + int TakenChoice() const { return m_Voted; } + const char *VoteDescription() const { return m_aDescription; } + const char *VoteCommand() const { return m_aCommand; } + + int m_Yes, m_No, m_Pass, m_Total; +}; + +#endif diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp deleted file mode 100644 index e04e1840..00000000 --- a/src/game/client/components/voting.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#include <game/client/component.hpp> -#include <game/client/ui.hpp> -#include <engine/e_memheap.h> - -class VOTING : public COMPONENT -{ - HEAP *heap; - - static void con_callvote(void *result, void *user_data); - static void con_vote(void *result, void *user_data); - - int64 closetime; - char description[512]; - char command[512]; - int voted; - - void clearoptions(); - void callvote(const char *type, const char *value); - -public: - - struct VOTEOPTION - { - VOTEOPTION *next; - VOTEOPTION *prev; - char command[1]; - }; - VOTEOPTION *first; - VOTEOPTION *last; - - VOTING(); - virtual void on_reset(); - virtual void on_console_init(); - virtual void on_message(int msgtype, void *rawmsg); - virtual void on_render(); - - void render_bars(CUIRect bars, bool text); - - void callvote_kick(int client_id); - void callvote_option(int option); - - void vote(int v); // -1 = no, 1 = yes - - int seconds_left() { return (closetime - time_get())/time_freq(); } - bool is_voting() { return closetime != 0; } - int taken_choice() const { return voted; } - const char *vote_description() const { return description; } - const char *vote_command() const { return command; } - - int yes, no, pass, total; -}; - diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 25a42620..d59a7a04 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1,82 +1,87 @@ -#include <string.h> -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> -#include <engine/e_demorec.h> - -#include <game/generated/g_protocol.hpp> -#include <game/generated/gc_data.hpp> - -#include <game/layers.hpp> -#include <game/localization.hpp> -#include "render.hpp" - -#include "gameclient.hpp" - -#include "components/binds.hpp" -#include "components/broadcast.hpp" -#include "components/camera.hpp" -#include "components/chat.hpp" -#include "components/console.hpp" -#include "components/controls.hpp" -#include "components/damageind.hpp" -#include "components/debughud.hpp" -#include "components/effects.hpp" -#include "components/emoticon.hpp" -#include "components/flow.hpp" -#include "components/hud.hpp" -#include "components/items.hpp" -#include "components/killmessages.hpp" -#include "components/mapimages.hpp" -#include "components/maplayers.hpp" -#include "components/menus.hpp" -#include "components/motd.hpp" -#include "components/particles.hpp" -#include "components/players.hpp" -#include "components/nameplates.hpp" -#include "components/scoreboard.hpp" -#include "components/skins.hpp" -#include "components/sounds.hpp" -#include "components/voting.hpp" - -GAMECLIENT gameclient; +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/sound.h> +#include <engine/demo.h> +#include <engine/map.h> +#include <engine/storage.h> +#include <engine/serverbrowser.h> +#include <engine/shared/demorec.h> +#include <engine/shared/config.h> + +#include <game/generated/protocol.h> +#include <game/generated/client_data.h> + +#include <game/localization.h> +#include <game/version.h> +#include "render.h" + +#include "gameclient.h" + +#include "components/binds.h" +#include "components/broadcast.h" +#include "components/camera.h" +#include "components/chat.h" +#include "components/console.h" +#include "components/controls.h" +#include "components/damageind.h" +#include "components/debughud.h" +#include "components/effects.h" +#include "components/emoticon.h" +#include "components/flow.h" +#include "components/hud.h" +#include "components/items.h" +#include "components/killmessages.h" +#include "components/mapimages.h" +#include "components/maplayers.h" +#include "components/menus.h" +#include "components/motd.h" +#include "components/particles.h" +#include "components/players.h" +#include "components/nameplates.h" +#include "components/scoreboard.h" +#include "components/skins.h" +#include "components/sounds.h" +#include "components/voting.h" + +CGameClient g_GameClient; // instanciate all systems -static KILLMESSAGES killmessages; -static CAMERA camera; -static CHAT chat; -static MOTD motd; -static BROADCAST broadcast; -static CONSOLE console; -static BINDS binds; -static PARTICLES particles; -static MENUS menus; -static SKINS skins; -static FLOW flow; -static HUD hud; -static DEBUGHUD debughud; -static CONTROLS controls; -static EFFECTS effects; -static SCOREBOARD scoreboard; -static SOUNDS sounds; -static EMOTICON emoticon; -static DAMAGEIND damageind; -static VOTING voting; - -static PLAYERS players; -static NAMEPLATES nameplates; -static ITEMS items; -static MAPIMAGES mapimages; - -static MAPLAYERS maplayers_background(MAPLAYERS::TYPE_BACKGROUND); -static MAPLAYERS maplayers_foreground(MAPLAYERS::TYPE_FOREGROUND); - -GAMECLIENT::STACK::STACK() { num = 0; } -void GAMECLIENT::STACK::add(class COMPONENT *component) { components[num++] = component; } - -static int load_current; -static int load_total; - -static void load_sounds_thread(void *do_render) +static CKillMessages gs_KillMessages; +static CCamera gs_Camera; +static CChat gs_Chat; +static CMotd gs_Motd; +static CBroadcast gs_Broadcast; +static CGameConsole gs_GameConsole; +static CBinds gs_Binds; +static CParticles gs_Particles; +static CMenus gs_Menus; +static CSkins gs_Skins; +static CFlow gs_Flow; +static CHud gs_Hud; +static CDebugHud gs_DebugHud; +static CControls gs_Controls; +static CEffects gs_Effects; +static CScoreboard gs_Scoreboard; +static CSounds gs_Sounds; +static CEmoticon gs_Emoticon; +static CDamageInd gsDamageInd; +static CVoting gs_Voting; + +static CPlayers gs_Players; +static CNamePlates gs_NamePlates; +static CItems gs_Items; +static CMapImages gs_MapImages; + +static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND); +static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND); + +CGameClient::CStack::CStack() { m_Num = 0; } +void CGameClient::CStack::Add(class CComponent *pComponent) { m_paComponents[m_Num++] = pComponent; } + +static int gs_LoadCurrent; +static int gs_LoadTotal; + +/*static void load_sounds_thread(void *do_render) { // load sounds for(int s = 0; s < data->num_sounds; s++) @@ -85,274 +90,235 @@ static void load_sounds_thread(void *do_render) gameclient.menus->render_loading(load_current/(float)load_total); for(int i = 0; i < data->sounds[s].num_sounds; i++) { - int id = snd_load_wv(data->sounds[s].sounds[i].filename); + int id = Sound()->LoadWV(data->sounds[s].sounds[i].filename); data->sounds[s].sounds[i].id = id; } if(do_render) load_current++; } -} +}*/ -static void con_serverdummy(void *result, void *user_data) +static void ConServerDummy(IConsole::IResult *pResult, void *pUserData) { dbg_msg("client", "this command is not available on the client"); } -#include <base/tl/sorted_array.hpp> - -void GAMECLIENT::on_console_init() -{ - if(0) - { - int ints[4] = {0,1,2,3}; - for(int s = 1; s < 4; s++) - { - //s = 2; - plain_range_sorted<int> test_sorted_range(ints, ints+s); - plain_range_sorted<int> res1, res2; - - //res2 = partition_binary(test_sorted_range, 1); - - //for(int i = 0; i < 4; i++) - // dbg_assert(partition_linear(test_sorted_range, i).front() == i, "partition linear failed"); - - - dbg_msg("", "size %d", s); - - for(int i = -1; i < 5; i++) - { - res1 = partition_linear(test_sorted_range, i); - dbg_msg("", "\tlin %d == %d", i, res1.empty()?-1:res1.front()); +#include <base/tl/sorted_array.h> - res2 = partition_binary(test_sorted_range, i); - dbg_msg("", "\tbin %d == %d", i, res2.empty()?-1:res2.front()); - //dbg_assert(partition_binary(plain_range_sorted<int>(ints, ints+6), i).front() == i+1, "partition binary failed"); - } - } //*/ +const char *CGameClient::Version() { return GAME_VERSION; } +const char *CGameClient::NetVersion() { return GAME_NETVERSION; } +const char *CGameClient::GetItemName(int Type) { return m_NetObjHandler.GetObjName(Type); } - sorted_array<int> test; - test.add(4); - test.add(1); - - for(int i = 0; i < 100; i++) - { - int this_add = rand(); - test.add(this_add); - if(!sort_verify(test.all())) - { - dbg_msg("", "error inserting %d", this_add); - for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front()) - dbg_msg("", "%d", r.front()); - exit(-1); - } - }/* - - - test.add(1); - test.add(4); - test.add(3); - test.add(4); - test.add(3); - test.add(2); - //test.insert(1, 1); - for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front()) - dbg_msg("", "%d", r.front()); - */ - - sort_verify(test.all()); - /* - for(int i = 0; i < 15; i++) - { - dbg_msg("", "found %d == %d", i, !find_binary(test.all(), i).empty()); - }*/ - - exit(-1); - } +void CGameClient::OnConsoleInit() +{ + m_pClient = Kernel()->RequestInterface<IClient>(); + m_pGraphics = Kernel()->RequestInterface<IGraphics>(); + m_pTextRender = Kernel()->RequestInterface<ITextRender>(); + m_pSound = Kernel()->RequestInterface<ISound>(); + m_pInput = Kernel()->RequestInterface<IInput>(); + m_pConsole = Kernel()->RequestInterface<IConsole>(); + m_pStorage = Kernel()->RequestInterface<IStorage>(); + m_pDemoPlayer = Kernel()->RequestInterface<IDemoPlayer>(); + m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>(); // setup pointers - binds = &::binds; - console = &::console; - particles = &::particles; - menus = &::menus; - skins = &::skins; - chat = &::chat; - flow = &::flow; - camera = &::camera; - controls = &::controls; - effects = &::effects; - sounds = &::sounds; - motd = &::motd; - damageind = &::damageind; - mapimages = &::mapimages; - voting = &::voting; + m_pBinds = &::gs_Binds; + m_pGameConsole = &::gs_GameConsole; + m_pParticles = &::gs_Particles; + m_pMenus = &::gs_Menus; + m_pSkins = &::gs_Skins; + m_pChat = &::gs_Chat; + m_pFlow = &::gs_Flow; + m_pCamera = &::gs_Camera; + m_pControls = &::gs_Controls; + m_pEffects = &::gs_Effects; + m_pSounds = &::gs_Sounds; + m_pMotd = &::gs_Motd; + m_pDamageind = &::gsDamageInd; + m_pMapimages = &::gs_MapImages; + m_pVoting = &::gs_Voting; // make a list of all the systems, make sure to add them in the corrent render order - all.add(skins); - all.add(mapimages); - all.add(effects); // doesn't render anything, just updates effects - all.add(particles); - all.add(binds); - all.add(controls); - all.add(camera); - all.add(sounds); - all.add(voting); - all.add(particles); // doesn't render anything, just updates all the particles - - all.add(&maplayers_background); // first to render - all.add(&particles->render_trail); - all.add(&particles->render_explosions); - all.add(&items); - all.add(&players); - all.add(&maplayers_foreground); - all.add(&nameplates); - all.add(&particles->render_general); - all.add(damageind); - all.add(&hud); - all.add(&emoticon); - all.add(&killmessages); - all.add(chat); - all.add(&broadcast); - all.add(&debughud); - all.add(&scoreboard); - all.add(motd); - all.add(menus); - all.add(console); + m_All.Add(m_pSkins); + m_All.Add(m_pMapimages); + m_All.Add(m_pEffects); // doesn't render anything, just updates effects + m_All.Add(m_pParticles); + m_All.Add(m_pBinds); + m_All.Add(m_pControls); + m_All.Add(m_pCamera); + m_All.Add(m_pSounds); + m_All.Add(m_pVoting); + m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles + + m_All.Add(&gs_MapLayersBackGround); // first to render + m_All.Add(&m_pParticles->m_RenderTrail); + m_All.Add(&m_pParticles->m_RenderExplosions); + m_All.Add(&gs_Items); + m_All.Add(&gs_Players); + m_All.Add(&gs_MapLayersForeGround); + m_All.Add(&gs_NamePlates); + m_All.Add(&m_pParticles->m_RenderGeneral); + m_All.Add(m_pDamageind); + m_All.Add(&gs_Hud); + m_All.Add(&gs_Emoticon); + m_All.Add(&gs_KillMessages); + m_All.Add(m_pChat); + m_All.Add(&gs_Broadcast); + m_All.Add(&gs_DebugHud); + m_All.Add(&gs_Scoreboard); + m_All.Add(m_pMotd); + m_All.Add(m_pMenus); + m_All.Add(m_pGameConsole); // build the input stack - input.add(&menus->binder); // this will take over all input when we want to bind a key - input.add(&binds->special_binds); - input.add(console); - input.add(chat); // chat has higher prio due to tha you can quit it by pressing esc - input.add(motd); // for pressing esc to remove it - input.add(menus); - input.add(&emoticon); - input.add(controls); - input.add(binds); + m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key + m_Input.Add(&m_pBinds->m_SpecialBinds); + m_Input.Add(m_pGameConsole); + m_Input.Add(m_pChat); // chat has higher prio due to tha you can quit it by pressing esc + m_Input.Add(m_pMotd); // for pressing esc to remove it + m_Input.Add(m_pMenus); + m_Input.Add(&gs_Emoticon); + m_Input.Add(m_pControls); + m_Input.Add(m_pBinds); // add the some console commands - MACRO_REGISTER_COMMAND("team", "i", CFGFLAG_CLIENT, con_team, this, "Switch team"); - MACRO_REGISTER_COMMAND("kill", "", CFGFLAG_CLIENT, con_kill, this, "Kill yourself"); + Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); + Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself"); // register server dummy commands for tab completion - MACRO_REGISTER_COMMAND("tune", "si", CFGFLAG_SERVER, con_serverdummy, 0, "Tune variable to value"); - MACRO_REGISTER_COMMAND("tune_reset", "", CFGFLAG_SERVER, con_serverdummy, 0, "Reset tuning"); - MACRO_REGISTER_COMMAND("tune_dump", "", CFGFLAG_SERVER, con_serverdummy, 0, "Dump tuning"); - MACRO_REGISTER_COMMAND("change_map", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Change map"); - MACRO_REGISTER_COMMAND("restart", "?i", CFGFLAG_SERVER, con_serverdummy, 0, "Restart in x seconds"); - MACRO_REGISTER_COMMAND("broadcast", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Broadcast message"); - /*MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0);*/ - MACRO_REGISTER_COMMAND("set_team", "ii", CFGFLAG_SERVER, con_serverdummy, 0, "Set team of player to team"); - MACRO_REGISTER_COMMAND("addvote", "r", CFGFLAG_SERVER, con_serverdummy, 0, "Add a voting option"); - /*MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0);*/ + Console()->Register("tune", "si", CFGFLAG_SERVER, ConServerDummy, 0, "Tune variable to value"); + Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConServerDummy, 0, "Reset tuning"); + Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConServerDummy, 0, "Dump tuning"); + Console()->Register("change_map", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Change map"); + Console()->Register("restart", "?i", CFGFLAG_SERVER, ConServerDummy, 0, "Restart in x seconds"); + Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Broadcast message"); + //MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0); + Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConServerDummy, 0, "Set team of player to team"); + Console()->Register("addvote", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Add a voting option"); + //MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0); + + + // propagate pointers + m_UI.SetGraphics(Graphics(), TextRender()); + m_RenderTools.m_pGraphics = Graphics(); + m_RenderTools.m_pUI = UI(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->m_pClient = this; // let all the other components register their console commands - for(int i = 0; i < all.num; i++) - all.components[i]->on_console_init(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnConsoleInit(); // - { static COMMANDCHAIN chain; console_chain_command("player_name", &chain, conchain_special_infoupdate, this); } - { static COMMANDCHAIN chain; console_chain_command("player_use_custom_color", &chain, conchain_special_infoupdate, this); } - { static COMMANDCHAIN chain; console_chain_command("player_color_body", &chain, conchain_special_infoupdate, this); } - { static COMMANDCHAIN chain; console_chain_command("player_color_feet", &chain, conchain_special_infoupdate, this); } - { static COMMANDCHAIN chain; console_chain_command("player_skin", &chain, conchain_special_infoupdate, this); } - - - + Console()->Chain("player_name", ConchainSpecialInfoupdate, this); + Console()->Chain("player_use_custom_color", ConchainSpecialInfoupdate, this); + Console()->Chain("player_color_body", ConchainSpecialInfoupdate, this); + Console()->Chain("player_color_feet", ConchainSpecialInfoupdate, this); + Console()->Chain("player_skin", ConchainSpecialInfoupdate, this); // - suppress_events = false; + m_SuppressEvents = false; } -void GAMECLIENT::on_init() +void CGameClient::OnInit() { - // set the language - localization.load(config.cl_languagefile); + //m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>(); - // propagate pointers - m_UI.SetGraphics(Graphics()); - m_RenderTools.m_pGraphics = Graphics(); - m_RenderTools.m_pUI = UI(); - for(int i = 0; i < all.num; i++) - all.components[i]->client = this; + // set the language + g_Localization.Load(g_Config.m_ClLanguagefile); // init all components - for(int i = 0; i < all.num; i++) - all.components[i]->on_init(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnInit(); // setup item sizes for(int i = 0; i < NUM_NETOBJTYPES; i++) - snap_set_staticsize(i, netobj_get_size(i)); + Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); - int64 start = time_get(); + int64 Start = time_get(); // load default font - static FONT *default_font; + static CFont *pDefaultFont; //default_font = gfx_font_load("data/fonts/sazanami-gothic.ttf"); - default_font = gfx_font_load("data/fonts/vera.ttf"); - gfx_text_set_default_font(default_font); + pDefaultFont = TextRender()->LoadFont("data/fonts/vera.ttf"); + TextRender()->SetDefaultFont(pDefaultFont); - config.cl_threadsoundloading = 0; + g_Config.m_ClThreadsoundloading = 0; // setup load amount - load_total = data->num_images; - load_current = 0; - if(!config.cl_threadsoundloading) - load_total += data->num_sounds; + gs_LoadTotal = g_pData->m_NumImages; + gs_LoadCurrent = 0; + if(!g_Config.m_ClThreadsoundloading) + gs_LoadTotal += g_pData->m_NumSounds; // load textures - for(int i = 0; i < data->num_images; i++) + for(int i = 0; i < g_pData->m_NumImages; i++) { - gameclient.menus->render_loading(load_current/load_total); - data->images[i].id = Graphics()->LoadTexture(data->images[i].filename, IMG_AUTO, 0); - load_current++; + g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/gs_LoadTotal); + g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, CImageInfo::FORMAT_AUTO, 0); + gs_LoadCurrent++; } - ::skins.init(); + ::gs_Skins.Init(); + - if(config.cl_threadsoundloading) + // TODO: Refactor: fix threaded loading of sounds again + // load sounds + { + bool DoRender = true; + for(int s = 0; s < g_pData->m_NumSounds; s++) + { + if(DoRender) + g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal); + for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++) + { + int id = Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename); + g_pData->m_aSounds[s].m_aSounds[i].m_Id = id; + } + + if(DoRender) + gs_LoadCurrent++; + } + } + + /*if(config.cl_threadsoundloading) thread_create(load_sounds_thread, 0); else - load_sounds_thread((void*)1); + load_sounds_thread((void*)1);*/ - for(int i = 0; i < all.num; i++) - all.components[i]->on_reset(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnReset(); - int64 end = time_get(); - dbg_msg("", "%f.2ms", ((end-start)*1000)/(float)time_freq()); + int64 End = time_get(); + dbg_msg("", "%f.2ms", ((End-Start)*1000)/(float)time_freq()); - servermode = SERVERMODE_PURE; + m_ServerMode = SERVERMODE_PURE; } -void GAMECLIENT::on_save() -{ - for(int i = 0; i < all.num; i++) - all.components[i]->on_save(); -} - -void GAMECLIENT::dispatch_input() +void CGameClient::DispatchInput() { // handle mouse movement int x=0, y=0; - inp_mouse_relative(&x, &y); + Input()->MouseRelative(&x, &y); if(x || y) { - for(int h = 0; h < input.num; h++) + for(int h = 0; h < m_Input.m_Num; h++) { - if(input.components[h]->on_mousemove(x, y)) + if(m_Input.m_paComponents[h]->OnMouseMove(x, y)) break; } } // handle key presses - for(int i = 0; i < inp_num_events(); i++) + for(int i = 0; i < Input()->NumEvents(); i++) { - INPUT_EVENT e = inp_get_event(i); + IInput::CEvent e = Input()->GetEvent(i); - for(int h = 0; h < input.num; h++) + for(int h = 0; h < m_Input.m_Num; h++) { - if(input.components[h]->on_input(e)) + if(m_Input.m_paComponents[h]->OnInput(e)) { //dbg_msg("", "%d char=%d key=%d flags=%d", h, e.ch, e.key, e.flags); break; @@ -361,102 +327,104 @@ void GAMECLIENT::dispatch_input() } // clear all events for this frame - inp_clear_events(); + Input()->ClearEvents(); } -int GAMECLIENT::on_snapinput(int *data) +int CGameClient::OnSnapInput(int *pData) { - return controls->snapinput(data); + return m_pControls->SnapInput(pData); } -void GAMECLIENT::on_connected() +void CGameClient::OnConnected() { - layers_init(); - col_init(); - RenderTools()->render_tilemap_generate_skip(); + m_Layers.Init(Kernel()); + m_Collision.Init(Layers()); + + RenderTools()->RenderTilemapGenerateSkip(Layers()); - for(int i = 0; i < all.num; i++) + for(int i = 0; i < m_All.m_Num; i++) { - all.components[i]->on_mapload(); - all.components[i]->on_reset(); + m_All.m_paComponents[i]->OnMapLoad(); + m_All.m_paComponents[i]->OnReset(); } - SERVER_INFO current_server_info; - client_serverinfo(¤t_server_info); + CServerInfo CurrentServerInfo; + Client()->GetServerInfo(&CurrentServerInfo); - servermode = SERVERMODE_PURE; + m_ServerMode = SERVERMODE_PURE; + m_LastSendInfo = 0; // send the inital info - send_info(true); + SendInfo(true); } -void GAMECLIENT::on_reset() +void CGameClient::OnReset() { // clear out the invalid pointers - last_new_predicted_tick = -1; - mem_zero(&gameclient.snap, sizeof(gameclient.snap)); + m_LastNewPredictedTick = -1; + mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap)); for(int i = 0; i < MAX_CLIENTS; i++) { - clients[i].name[0] = 0; - clients[i].skin_id = 0; - clients[i].team = 0; - clients[i].angle = 0; - clients[i].emoticon = 0; - clients[i].emoticon_start = -1; - clients[i].skin_info.texture = gameclient.skins->get(0)->color_texture; - clients[i].skin_info.color_body = vec4(1,1,1,1); - clients[i].skin_info.color_feet = vec4(1,1,1,1); - clients[i].update_render_info(); + m_aClients[i].m_aName[0] = 0; + m_aClients[i].m_SkinId = 0; + m_aClients[i].m_Team = 0; + m_aClients[i].m_Angle = 0; + m_aClients[i].m_Emoticon = 0; + m_aClients[i].m_EmoticonStart = -1; + m_aClients[i].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(0)->m_ColorTexture; + m_aClients[i].m_SkinInfo.m_ColorBody = vec4(1,1,1,1); + m_aClients[i].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1); + m_aClients[i].UpdateRenderInfo(); } - for(int i = 0; i < all.num; i++) - all.components[i]->on_reset(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnReset(); } -void GAMECLIENT::update_local_character_pos() +void CGameClient::UpdateLocalCharacterPos() { - if(config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK) + if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!snap.local_character || (snap.local_character->health < 0) || (snap.gameobj && snap.gameobj->game_over)) + if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pLocalCharacter->m_Health < 0) || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver)) { // don't use predicted } else - local_character_pos = mix(predicted_prev_char.pos, predicted_char.pos, client_predintratick()); + m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick()); } - else if(snap.local_character && snap.local_prev_character) + else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { - local_character_pos = mix( - vec2(snap.local_prev_character->x, snap.local_prev_character->y), - vec2(snap.local_character->x, snap.local_character->y), client_intratick()); + m_LocalCharacterPos = mix( + vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y), + vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick()); } } -static void evolve(NETOBJ_CHARACTER *character, int tick) +static void Evolve(CNetObj_Character *pCharacter, int Tick) { - WORLD_CORE tempworld; - CHARACTER_CORE tempcore; - mem_zero(&tempcore, sizeof(tempcore)); - tempcore.world = &tempworld; - tempcore.read(character); + CWorldCore TempWorld; + CCharacterCore TempCore; + mem_zero(&TempCore, sizeof(TempCore)); + TempCore.Init(&TempWorld, g_GameClient.Collision()); + TempCore.Read(pCharacter); - while(character->tick < tick) + while(pCharacter->m_Tick < Tick) { - character->tick++; - tempcore.tick(false); - tempcore.move(); - tempcore.quantize(); + pCharacter->m_Tick++; + TempCore.Tick(false); + TempCore.Move(); + TempCore.Quantize(); } - tempcore.write(character); + TempCore.Write(pCharacter); } -void GAMECLIENT::on_render() +void CGameClient::OnRender() { /*Graphics()->Clear(1,0,0); @@ -474,25 +442,41 @@ void GAMECLIENT::on_render() return;*/ // update the local character position - update_local_character_pos(); + UpdateLocalCharacterPos(); // dispatch all input to systems - dispatch_input(); + DispatchInput(); // render all systems - for(int i = 0; i < all.num; i++) - all.components[i]->on_render(); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnRender(); // clear new tick flags - new_tick = false; - new_predicted_tick = false; + m_NewTick = false; + m_NewPredictedTick = false; + + // check if client info has to be resent + if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get()) + { + // resend if client info differs + if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalCid].m_aName) || + str_comp(g_Config.m_PlayerSkin, m_aClients[m_Snap.m_LocalCid].m_aSkinName) || + (g_GameClient.m_Snap.m_pGameobj && !(g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) && // no teamgame? + (g_Config.m_PlayerUseCustomColor != m_aClients[m_Snap.m_LocalCid].m_UseCustomColor || + g_Config.m_PlayerColorBody != m_aClients[m_Snap.m_LocalCid].m_ColorBody || + g_Config.m_PlayerColorFeet != m_aClients[m_Snap.m_LocalCid].m_ColorFeet))) + { + SendInfo(false); + } + m_LastSendInfo = 0; + } } -void GAMECLIENT::on_message(int msgtype) +void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { // special messages - if(msgtype == NETMSGTYPE_SV_EXTRAPROJECTILE) + if(MsgId == NETMSGTYPE_SV_EXTRAPROJECTILE) { /* int num = msg_unpack_int(); @@ -515,497 +499,492 @@ void GAMECLIENT::on_message(int msgtype) return;*/ } - else if(msgtype == NETMSGTYPE_SV_TUNEPARAMS) + else if(MsgId == NETMSGTYPE_SV_TUNEPARAMS) { // unpack the new tuning - TUNING_PARAMS new_tuning; - int *params = (int *)&new_tuning; - for(unsigned i = 0; i < sizeof(TUNING_PARAMS)/sizeof(int); i++) - params[i] = msg_unpack_int(); + CTuningParams NewTuning; + int *pParams = (int *)&NewTuning; + for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++) + pParams[i] = pUnpacker->GetInt(); // check for unpacking errors - if(msg_unpack_error()) + if(pUnpacker->Error()) return; - servermode = SERVERMODE_PURE; + m_ServerMode = SERVERMODE_PURE; // apply new tuning - tuning = new_tuning; + m_Tuning = NewTuning; return; } - void *rawmsg = netmsg_secure_unpack(msgtype); - if(!rawmsg) + void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); + if(!pRawMsg) { - dbg_msg("client", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on()); + dbg_msg("client", "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); return; } // TODO: this should be done smarter - for(int i = 0; i < all.num; i++) - all.components[i]->on_message(msgtype, rawmsg); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); - if(msgtype == NETMSGTYPE_SV_READYTOENTER) + if(MsgId == NETMSGTYPE_SV_READYTOENTER) { - client_entergame(); + Client()->EnterGame(); } - else if (msgtype == NETMSGTYPE_SV_EMOTICON) + else if (MsgId == NETMSGTYPE_SV_EMOTICON) { - NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg; + CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg; // apply - clients[msg->cid].emoticon = msg->emoticon; - clients[msg->cid].emoticon_start = client_tick(); + m_aClients[pMsg->m_Cid].m_Emoticon = pMsg->m_Emoticon; + m_aClients[pMsg->m_Cid].m_EmoticonStart = Client()->GameTick(); } - else if(msgtype == NETMSGTYPE_SV_SOUNDGLOBAL) + else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL) { - if(suppress_events) + if(m_SuppressEvents) return; - NETMSG_SV_SOUNDGLOBAL *msg = (NETMSG_SV_SOUNDGLOBAL *)rawmsg; - gameclient.sounds->play(SOUNDS::CHN_GLOBAL, msg->soundid, 1.0f, vec2(0,0)); + CNetMsg_Sv_SoundGlobal *pMsg = (CNetMsg_Sv_SoundGlobal *)pRawMsg; + g_GameClient.m_pSounds->Enqueue(pMsg->m_Soundid); } } -void GAMECLIENT::on_statechange(int new_state, int old_state) +void CGameClient::OnStateChange(int NewState, int OldState) { - if(demorec_isrecording()) - demorec_record_stop(); - - // reset everything - on_reset(); + // reset everything when not already connected (to keep gathered stuff) + if(NewState < IClient::STATE_ONLINE) + OnReset(); // then change the state - for(int i = 0; i < all.num; i++) - all.components[i]->on_statechange(new_state, old_state); + for(int i = 0; i < m_All.m_Num; i++) + m_All.m_paComponents[i]->OnStateChange(NewState, OldState); } +void CGameClient::OnShutdown() {} +void CGameClient::OnEnterGame() {} +void CGameClient::OnRconLine(const char *pLine) +{ + m_pGameConsole->PrintLine(1, pLine); +} -void GAMECLIENT::process_events() +void CGameClient::ProcessEvents() { - if(suppress_events) + if(m_SuppressEvents) return; - int snaptype = SNAP_CURRENT; - int num = snap_num_items(snaptype); - for(int index = 0; index < num; index++) + int SnapType = IClient::SNAP_CURRENT; + int Num = Client()->SnapNumItems(SnapType); + for(int Index = 0; Index < Num; Index++) { - SNAP_ITEM item; - const void *data = snap_get_item(snaptype, index, &item); + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(SnapType, Index, &Item); - if(item.type == NETEVENTTYPE_DAMAGEIND) + if(Item.m_Type == NETEVENTTYPE_DAMAGEIND) { - NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)data; - gameclient.effects->damage_indicator(vec2(ev->x, ev->y), get_direction(ev->angle)); + NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)pData; + g_GameClient.m_pEffects->DamageIndicator(vec2(ev->m_X, ev->m_Y), GetDirection(ev->m_Angle)); } - else if(item.type == NETEVENTTYPE_EXPLOSION) + else if(Item.m_Type == NETEVENTTYPE_EXPLOSION) { - NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)data; - gameclient.effects->explosion(vec2(ev->x, ev->y)); + NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)pData; + g_GameClient.m_pEffects->Explosion(vec2(ev->m_X, ev->m_Y)); } - else if(item.type == NETEVENTTYPE_HAMMERHIT) + else if(Item.m_Type == NETEVENTTYPE_HAMMERHIT) { - NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)data; - gameclient.effects->hammerhit(vec2(ev->x, ev->y)); + NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)pData; + g_GameClient.m_pEffects->HammerHit(vec2(ev->m_X, ev->m_Y)); } - else if(item.type == NETEVENTTYPE_SPAWN) + else if(Item.m_Type == NETEVENTTYPE_SPAWN) { - NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)data; - gameclient.effects->playerspawn(vec2(ev->x, ev->y)); + NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)pData; + g_GameClient.m_pEffects->PlayerSpawn(vec2(ev->m_X, ev->m_Y)); } - else if(item.type == NETEVENTTYPE_DEATH) + else if(Item.m_Type == NETEVENTTYPE_DEATH) { - NETEVENT_DEATH *ev = (NETEVENT_DEATH *)data; - gameclient.effects->playerdeath(vec2(ev->x, ev->y), ev->cid); + NETEVENT_DEATH *ev = (NETEVENT_DEATH *)pData; + g_GameClient.m_pEffects->PlayerDeath(vec2(ev->m_X, ev->m_Y), ev->m_ClientId); } - else if(item.type == NETEVENTTYPE_SOUNDWORLD) + else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD) { - NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)data; - gameclient.sounds->play(SOUNDS::CHN_WORLD, ev->soundid, 1.0f, vec2(ev->x, ev->y)); + NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)pData; + g_GameClient.m_pSounds->Play(CSounds::CHN_WORLD, ev->m_SoundId, 1.0f, vec2(ev->m_X, ev->m_Y)); } } } -void GAMECLIENT::on_snapshot() +void CGameClient::OnNewSnapshot() { - new_tick = true; + m_NewTick = true; // clear out the invalid pointers - mem_zero(&gameclient.snap, sizeof(gameclient.snap)); - snap.local_cid = -1; + mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap)); + m_Snap.m_LocalCid = -1; // secure snapshot { - int num = snap_num_items(SNAP_CURRENT); - for(int index = 0; index < num; index++) + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); + for(int Index = 0; Index < Num; Index++) { - SNAP_ITEM item; - void *data = snap_get_item(SNAP_CURRENT, index, &item); - if(netobj_validate(item.type, data, item.datasize) != 0) + IClient::CSnapItem Item; + void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); + if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0) { - if(config.debug) - dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", index, item.type, netobj_get_name(item.type), item.datasize, item.id); - snap_invalidate_item(SNAP_CURRENT, index); + if(g_Config.m_Debug) + dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_Id); + Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index); } } } - process_events(); + ProcessEvents(); - if(config.dbg_stress) + if(g_Config.m_DbgStress) { - if((client_tick()%100) == 0) + if((Client()->GameTick()%100) == 0) { - char message[64]; - int msglen = rand()%(sizeof(message)-1); - for(int i = 0; i < msglen; i++) - message[i] = 'a'+(rand()%('z'-'a')); - message[msglen] = 0; + char aMessage[64]; + int MsgLen = rand()%(sizeof(aMessage)-1); + for(int i = 0; i < MsgLen; i++) + aMessage[i] = 'a'+(rand()%('z'-'a')); + aMessage[MsgLen] = 0; - NETMSG_CL_SAY msg; - msg.team = rand()&1; - msg.message = message; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_Say Msg; + Msg.m_Team = rand()&1; + Msg.m_pMessage = aMessage; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } } // go trough all the items in the snapshot and gather the info we want { - snap.team_size[0] = snap.team_size[1] = 0; + m_Snap.m_aTeamSize[0] = m_Snap.m_aTeamSize[1] = 0; - int num = snap_num_items(SNAP_CURRENT); - for(int i = 0; i < num; i++) + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); + for(int i = 0; i < Num; i++) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + IClient::CSnapItem Item; + const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item); - if(item.type == NETOBJTYPE_CLIENT_INFO) + if(Item.m_Type == NETOBJTYPE_CLIENTINFO) { - const NETOBJ_CLIENT_INFO *info = (const NETOBJ_CLIENT_INFO *)data; - int cid = item.id; - ints_to_str(&info->name0, 6, clients[cid].name); - ints_to_str(&info->skin0, 6, clients[cid].skin_name); + const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData; + int Cid = Item.m_Id; + IntsToStr(&pInfo->m_Name0, 6, m_aClients[Cid].m_aName); + IntsToStr(&pInfo->m_Skin0, 6, m_aClients[Cid].m_aSkinName); - clients[cid].use_custom_color = info->use_custom_color; - clients[cid].color_body = info->color_body; - clients[cid].color_feet = info->color_feet; + m_aClients[Cid].m_UseCustomColor = pInfo->m_UseCustomColor; + m_aClients[Cid].m_ColorBody = pInfo->m_ColorBody; + m_aClients[Cid].m_ColorFeet = pInfo->m_ColorFeet; // prepare the info - if(clients[cid].skin_name[0] == 'x' || clients[cid].skin_name[1] == '_') - str_copy(clients[cid].skin_name, "default", 64); + if(m_aClients[Cid].m_aSkinName[0] == 'x' || m_aClients[Cid].m_aSkinName[1] == '_') + str_copy(m_aClients[Cid].m_aSkinName, "default", 64); - clients[cid].skin_info.color_body = skins->get_color(clients[cid].color_body); - clients[cid].skin_info.color_feet = skins->get_color(clients[cid].color_feet); - clients[cid].skin_info.size = 64; + m_aClients[Cid].m_SkinInfo.m_ColorBody = m_pSkins->GetColor(m_aClients[Cid].m_ColorBody); + m_aClients[Cid].m_SkinInfo.m_ColorFeet = m_pSkins->GetColor(m_aClients[Cid].m_ColorFeet); + m_aClients[Cid].m_SkinInfo.m_Size = 64; // find new skin - clients[cid].skin_id = gameclient.skins->find(clients[cid].skin_name); - if(clients[cid].skin_id < 0) + m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find(m_aClients[Cid].m_aSkinName); + if(m_aClients[Cid].m_SkinId < 0) { - clients[cid].skin_id = gameclient.skins->find("default"); - if(clients[cid].skin_id < 0) - clients[cid].skin_id = 0; + m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find("default"); + if(m_aClients[Cid].m_SkinId < 0) + m_aClients[Cid].m_SkinId = 0; } - if(clients[cid].use_custom_color) - clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->color_texture; + if(m_aClients[Cid].m_UseCustomColor) + m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_ColorTexture; else { - clients[cid].skin_info.texture = gameclient.skins->get(clients[cid].skin_id)->org_texture; - clients[cid].skin_info.color_body = vec4(1,1,1,1); - clients[cid].skin_info.color_feet = vec4(1,1,1,1); + m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_OrgTexture; + m_aClients[Cid].m_SkinInfo.m_ColorBody = vec4(1,1,1,1); + m_aClients[Cid].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1); } - clients[cid].update_render_info(); - gameclient.snap.num_players++; + m_aClients[Cid].UpdateRenderInfo(); + g_GameClient.m_Snap.m_NumPlayers++; } - else if(item.type == NETOBJTYPE_PLAYER_INFO) + else if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { - const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data; + const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; - clients[info->cid].team = info->team; - snap.player_infos[info->cid] = info; + m_aClients[pInfo->m_ClientId].m_Team = pInfo->m_Team; + m_Snap.m_paPlayerInfos[pInfo->m_ClientId] = pInfo; - if(info->local) + if(pInfo->m_Local) { - snap.local_cid = item.id; - snap.local_info = info; + m_Snap.m_LocalCid = Item.m_Id; + m_Snap.m_pLocalInfo = pInfo; - if (info->team == -1) - snap.spectate = true; + if (pInfo->m_Team == -1) + m_Snap.m_Spectate = true; } // calculate team-balance - if(info->team != -1) - snap.team_size[info->team]++; + if(pInfo->m_Team != -1) + m_Snap.m_aTeamSize[pInfo->m_Team]++; } - else if(item.type == NETOBJTYPE_CHARACTER) + else if(Item.m_Type == NETOBJTYPE_CHARACTER) { - const void *old = snap_find_item(SNAP_PREV, NETOBJTYPE_CHARACTER, item.id); - if(old) + const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_Id); + if(pOld) { - snap.characters[item.id].active = true; - snap.characters[item.id].prev = *((const NETOBJ_CHARACTER *)old); - snap.characters[item.id].cur = *((const NETOBJ_CHARACTER *)data); - - if(snap.characters[item.id].prev.tick) - evolve(&snap.characters[item.id].prev, client_prevtick()); - if(snap.characters[item.id].cur.tick) - evolve(&snap.characters[item.id].cur, client_tick()); + m_Snap.m_aCharacters[Item.m_Id].m_Active = true; + m_Snap.m_aCharacters[Item.m_Id].m_Prev = *((const CNetObj_Character *)pOld); + m_Snap.m_aCharacters[Item.m_Id].m_Cur = *((const CNetObj_Character *)pData); + + if(m_Snap.m_aCharacters[Item.m_Id].m_Prev.m_Tick) + Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Prev, Client()->PrevGameTick()); + if(m_Snap.m_aCharacters[Item.m_Id].m_Cur.m_Tick) + Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Cur, Client()->GameTick()); } } - else if(item.type == NETOBJTYPE_GAME) - snap.gameobj = (NETOBJ_GAME *)data; - else if(item.type == NETOBJTYPE_FLAG) - snap.flags[item.id%2] = (const NETOBJ_FLAG *)data; + else if(Item.m_Type == NETOBJTYPE_GAME) + m_Snap.m_pGameobj = (CNetObj_Game *)pData; + else if(Item.m_Type == NETOBJTYPE_FLAG) + m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData; } } // setup local pointers - if(snap.local_cid >= 0) + if(m_Snap.m_LocalCid >= 0) { - SNAPSTATE::CHARACTERINFO *c = &snap.characters[snap.local_cid]; - if(c->active) + CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalCid]; + if(c->m_Active) { - snap.local_character = &c->cur; - snap.local_prev_character = &c->prev; - local_character_pos = vec2(snap.local_character->x, snap.local_character->y); + m_Snap.m_pLocalCharacter = &c->m_Cur; + m_Snap.m_pLocalPrevCharacter = &c->m_Prev; + m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y); } } else - snap.spectate = true; + m_Snap.m_Spectate = true; - TUNING_PARAMS standard_tuning; - SERVER_INFO current_server_info; - client_serverinfo(¤t_server_info); - if(current_server_info.gametype[0] != '0') + CTuningParams StandardTuning; + CServerInfo CurrentServerInfo; + Client()->GetServerInfo(&CurrentServerInfo); + if(CurrentServerInfo.m_aGameType[0] != '0') { - if(strcmp(current_server_info.gametype, "DM") != 0 && strcmp(current_server_info.gametype, "TDM") != 0 && strcmp(current_server_info.gametype, "CTF") != 0) - servermode = SERVERMODE_MOD; - else if(memcmp(&standard_tuning, &tuning, sizeof(TUNING_PARAMS)) == 0) - servermode = SERVERMODE_PURE; + if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0) + m_ServerMode = SERVERMODE_MOD; + else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0) + m_ServerMode = SERVERMODE_PURE; else - servermode = SERVERMODE_PUREMOD; + m_ServerMode = SERVERMODE_PUREMOD; } // update render info for(int i = 0; i < MAX_CLIENTS; i++) - clients[i].update_render_info(); + m_aClients[i].UpdateRenderInfo(); } -void GAMECLIENT::on_predict() +void CGameClient::OnPredict() { // store the previous values so we can detect prediction errors - CHARACTER_CORE before_prev_char = predicted_prev_char; - CHARACTER_CORE before_char = predicted_char; + CCharacterCore BeforePrevChar = m_PredictedPrevChar; + CCharacterCore BeforeChar = m_PredictedChar; // we can't predict without our own id or own character - if(snap.local_cid == -1 || !snap.characters[snap.local_cid].active) + if(m_Snap.m_LocalCid == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalCid].m_Active) return; // don't predict anything if we are paused - if(snap.gameobj && snap.gameobj->paused) + if(m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_Paused) { - if(snap.local_character) - predicted_char.read(snap.local_character); - if(snap.local_prev_character) - predicted_prev_char.read(snap.local_prev_character); + if(m_Snap.m_pLocalCharacter) + m_PredictedChar.Read(m_Snap.m_pLocalCharacter); + if(m_Snap.m_pLocalPrevCharacter) + m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter); return; } // repredict character - WORLD_CORE world; - world.tuning = tuning; + CWorldCore World; + World.m_Tuning = m_Tuning; // search for players for(int i = 0; i < MAX_CLIENTS; i++) { - if(!snap.characters[i].active) + if(!m_Snap.m_aCharacters[i].m_Active) continue; - gameclient.clients[i].predicted.world = &world; - world.characters[i] = &gameclient.clients[i].predicted; - gameclient.clients[i].predicted.read(&snap.characters[i].cur); + g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision()); + World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted; + g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); } // predict - for(int tick = client_tick()+1; tick <= client_predtick(); tick++) + for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++) { // fetch the local - if(tick == client_predtick() && world.characters[snap.local_cid]) - predicted_prev_char = *world.characters[snap.local_cid]; + if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid]) + m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalCid]; // first calculate where everyone should move for(int c = 0; c < MAX_CLIENTS; c++) { - if(!world.characters[c]) + if(!World.m_apCharacters[c]) continue; - mem_zero(&world.characters[c]->input, sizeof(world.characters[c]->input)); - if(snap.local_cid == c) + mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input)); + if(m_Snap.m_LocalCid == c) { // apply player input - int *input = client_get_input(tick); - if(input) - world.characters[c]->input = *((NETOBJ_PLAYER_INPUT*)input); - world.characters[c]->tick(true); + int *pInput = Client()->GetInput(Tick); + if(pInput) + World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput); + World.m_apCharacters[c]->Tick(true); } else - world.characters[c]->tick(false); + World.m_apCharacters[c]->Tick(false); } // move all players and quantize their data for(int c = 0; c < MAX_CLIENTS; c++) { - if(!world.characters[c]) + if(!World.m_apCharacters[c]) continue; - world.characters[c]->move(); - world.characters[c]->quantize(); + World.m_apCharacters[c]->Move(); + World.m_apCharacters[c]->Quantize(); } // check if we want to trigger effects - if(tick > last_new_predicted_tick) + if(Tick > m_LastNewPredictedTick) { - last_new_predicted_tick = tick; - new_predicted_tick = true; + m_LastNewPredictedTick = Tick; + m_NewPredictedTick = true; - if(snap.local_cid != -1 && world.characters[snap.local_cid]) + if(m_Snap.m_LocalCid != -1 && World.m_apCharacters[m_Snap.m_LocalCid]) { - vec2 pos = world.characters[snap.local_cid]->pos; - int events = world.characters[snap.local_cid]->triggered_events; - if(events&COREEVENT_GROUND_JUMP) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); + vec2 Pos = World.m_apCharacters[m_Snap.m_LocalCid]->m_Pos; + int Events = World.m_apCharacters[m_Snap.m_LocalCid]->m_TriggeredEvents; + if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos); /*if(events&COREEVENT_AIR_JUMP) { - gameclient.effects->air_jump(pos); - gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos); + GameClient.effects->air_jump(pos); + GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos); }*/ //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); //if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos); - if(events&COREEVENT_HOOK_ATTACH_GROUND) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, pos); - if(events&COREEVENT_HOOK_HIT_NOHOOK) gameclient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, pos); + if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos); + if(Events&COREEVENT_HOOK_HIT_NOHOOK) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos); //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); } } - if(tick == client_predtick() && world.characters[snap.local_cid]) - predicted_char = *world.characters[snap.local_cid]; + if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid]) + m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalCid]; } - if(config.debug && config.cl_predict && predicted_tick == client_predtick()) + if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick()) { - NETOBJ_CHARACTER_CORE before = {0}, now = {0}, before_prev = {0}, now_prev = {0}; - before_char.write(&before); - before_prev_char.write(&before_prev); - predicted_char.write(&now); - predicted_prev_char.write(&now_prev); + CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; + BeforeChar.Write(&Before); + BeforePrevChar.Write(&BeforePrev); + m_PredictedChar.Write(&Now); + m_PredictedPrevChar.Write(&NowPrev); - if(mem_comp(&before, &now, sizeof(NETOBJ_CHARACTER_CORE)) != 0) + if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0) { dbg_msg("client", "prediction error"); - for(unsigned i = 0; i < sizeof(NETOBJ_CHARACTER_CORE)/sizeof(int); i++) - if(((int *)&before)[i] != ((int *)&now)[i]) + for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++) + if(((int *)&Before)[i] != ((int *)&Now)[i]) { - dbg_msg("", "\t%d %d %d (%d %d)", i, ((int *)&before)[i], ((int *)&now)[i], ((int *)&before_prev)[i], ((int *)&now_prev)[i]); + dbg_msg("", "\t%d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]); } } } - predicted_tick = client_predtick(); + m_PredictedTick = Client()->PredGameTick(); } -void GAMECLIENT::CLIENT_DATA::update_render_info() +void CGameClient::CClientData::UpdateRenderInfo() { - render_info = skin_info; + m_RenderInfo = m_SkinInfo; // force team colors - if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) + if(g_GameClient.m_Snap.m_pGameobj && g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) { - const int team_colors[2] = {65387, 10223467}; - if(team >= 0 || team <= 1) + const int TeamColors[2] = {65387, 10223467}; + if(m_Team >= 0 || m_Team <= 1) { - render_info.texture = gameclient.skins->get(skin_id)->color_texture; - render_info.color_body = gameclient.skins->get_color(team_colors[team]); - render_info.color_feet = gameclient.skins->get_color(team_colors[team]); + m_RenderInfo.m_Texture = g_GameClient.m_pSkins->Get(m_SkinId)->m_ColorTexture; + m_RenderInfo.m_ColorBody = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]); + m_RenderInfo.m_ColorFeet = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]); } } } -void GAMECLIENT::send_switch_team(int team) +void CGameClient::SendSwitchTeam(int Team) { - NETMSG_CL_SETTEAM msg; - msg.team = team; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_SetTeam Msg; + Msg.m_Team = Team; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } -void GAMECLIENT::send_info(bool start) +void CGameClient::SendInfo(bool Start) { - if(start) + if(Start) { - NETMSG_CL_STARTINFO msg; - msg.name = config.player_name; - msg.skin = config.player_skin; - msg.use_custom_color = config.player_use_custom_color; - msg.color_body = config.player_color_body; - msg.color_feet = config.player_color_feet; - msg.pack(MSGFLAG_VITAL); + CNetMsg_Cl_StartInfo Msg; + Msg.m_pName = g_Config.m_PlayerName; + Msg.m_pSkin = g_Config.m_PlayerSkin; + Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor; + Msg.m_ColorBody = g_Config.m_PlayerColorBody; + Msg.m_ColorFeet = g_Config.m_PlayerColorFeet; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } else { - NETMSG_CL_CHANGEINFO msg; - msg.name = config.player_name; - msg.skin = config.player_skin; - msg.use_custom_color = config.player_use_custom_color; - msg.color_body = config.player_color_body; - msg.color_feet = config.player_color_feet; - msg.pack(MSGFLAG_VITAL); + CNetMsg_Cl_ChangeInfo Msg; + Msg.m_pName = g_Config.m_PlayerName; + Msg.m_pSkin = g_Config.m_PlayerSkin; + Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor; + Msg.m_ColorBody = g_Config.m_PlayerColorBody; + Msg.m_ColorFeet = g_Config.m_PlayerColorFeet; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + + // activate timer to resend the info if it gets filtered + if(!m_LastSendInfo || m_LastSendInfo+time_freq()*5 < time_get()) + m_LastSendInfo = time_get(); } - client_send_msg(); } -void GAMECLIENT::send_kill(int client_id) +void CGameClient::SendKill(int ClientId) { - NETMSG_CL_KILL msg; - msg.pack(MSGFLAG_VITAL); - client_send_msg(); + CNetMsg_Cl_Kill Msg; + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } -void GAMECLIENT::con_team(void *result, void *user_data) +void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData) { - ((GAMECLIENT*)user_data)->send_switch_team(console_arg_int(result, 0)); + ((CGameClient*)pUserData)->SendSwitchTeam(pResult->GetInteger(0)); } -void GAMECLIENT::con_kill(void *result, void *user_data) +void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData) { - ((GAMECLIENT*)user_data)->send_kill(-1); + ((CGameClient*)pUserData)->SendKill(-1); } -void GAMECLIENT::conchain_special_infoupdate(void *result, void *user_data, CONSOLE_CALLBACK cb, void *cbuser) +void CGameClient::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { - cb(result, cbuser); - if(console_arg_num(result)) - ((GAMECLIENT*)user_data)->send_info(false); -} - -void GAMECLIENT::SetEngine(class IEngine *pEngine) -{ - m_pEngine = pEngine; - - // digg out some pointers - m_pGraphics = m_pEngine->Graphics(); + pfnCallback(pResult, pCallbackUserData); + if(pResult->NumArguments()) + ((CGameClient*)pUserData)->SendInfo(false); } -IGameClient *CreateGameClient(IEngine *pEngine) +IGameClient *CreateGameClient() { - gameclient.SetEngine(pEngine); - return &gameclient; + return &g_GameClient; } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h new file mode 100644 index 00000000..b91b4b50 --- /dev/null +++ b/src/game/client/gameclient.h @@ -0,0 +1,208 @@ +#ifndef GAME_CLIENT_GAMECLIENT_H +#define GAME_CLIENT_GAMECLIENT_H + +#include <base/vmath.h> +#include <engine/client.h> +#include <engine/console.h> +#include <game/layers.h> +#include <game/gamecore.h> +#include "render.h" + +class CGameClient : public IGameClient +{ + class CStack + { + public: + enum + { + MAX_COMPONENTS = 64, + }; + + CStack(); + void Add(class CComponent *pComponent); + + class CComponent *m_paComponents[MAX_COMPONENTS]; + int m_Num; + }; + + CStack m_All; + CStack m_Input; + CNetObjHandler m_NetObjHandler; + + class IInput *m_pInput; + class IGraphics *m_pGraphics; + class ITextRender *m_pTextRender; + class IClient *m_pClient; + class ISound *m_pSound; + class IConsole *m_pConsole; + class IStorage *m_pStorage; + class IDemoPlayer *m_pDemoPlayer; + class IServerBrowser *m_pServerBrowser; + + CLayers m_Layers; + class CCollision m_Collision; + CUI m_UI; + + void DispatchInput(); + void ProcessEvents(); + void UpdateLocalCharacterPos(); + + int m_PredictedTick; + int m_LastNewPredictedTick; + + int64 m_LastSendInfo; + + static void ConTeam(IConsole::IResult *pResult, void *pUserData); + static void ConKill(IConsole::IResult *pResult, void *pUserData); + + static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + +public: + IKernel *Kernel() { return IInterface::Kernel(); } + class IGraphics *Graphics() const { return m_pGraphics; } + class IClient *Client() const { return m_pClient; } + class CUI *UI() { return &m_UI; } + class ISound *Sound() const { return m_pSound; } + class IInput *Input() const { return m_pInput; } + class IStorage *Storage() const { return m_pStorage; } + class IConsole *Console() { return m_pConsole; } + class ITextRender *TextRender() const { return m_pTextRender; } + class IDemoPlayer *DemoPlayer() const { return m_pDemoPlayer; } + class IServerBrowser *ServerBrowser() const { return m_pServerBrowser; } + class CRenderTools *RenderTools() { return &m_RenderTools; } + class CLayers *Layers() { return &m_Layers; }; + class CCollision *Collision() { return &m_Collision; }; + + + bool m_SuppressEvents; + bool m_NewTick; + bool m_NewPredictedTick; + + // TODO: move this + CTuningParams m_Tuning; + + enum + { + SERVERMODE_PURE=0, + SERVERMODE_MOD, + SERVERMODE_PUREMOD, + }; + int m_ServerMode; + + vec2 m_LocalCharacterPos; + + // predicted players + CCharacterCore m_PredictedPrevChar; + CCharacterCore m_PredictedChar; + + // snap pointers + struct CSnapState + { + const CNetObj_Character *m_pLocalCharacter; + const CNetObj_Character *m_pLocalPrevCharacter; + const CNetObj_PlayerInfo *m_pLocalInfo; + const CNetObj_Flag *m_paFlags[2]; + const CNetObj_Game *m_pGameobj; + + const CNetObj_PlayerInfo *m_paPlayerInfos[MAX_CLIENTS]; + const CNetObj_PlayerInfo *m_paInfoByScore[MAX_CLIENTS]; + + int m_LocalCid; + int m_NumPlayers; + int m_aTeamSize[2]; + bool m_Spectate; + + // + struct CCharacterInfo + { + bool m_Active; + + // snapshots + CNetObj_Character m_Prev; + CNetObj_Character m_Cur; + + // interpolated position + vec2 m_Position; + }; + + CCharacterInfo m_aCharacters[MAX_CLIENTS]; + }; + + CSnapState m_Snap; + + // client data + struct CClientData + { + int m_UseCustomColor; + int m_ColorBody; + int m_ColorFeet; + + char m_aName[64]; + char m_aSkinName[64]; + int m_SkinId; + int m_SkinColor; + int m_Team; + int m_Emoticon; + int m_EmoticonStart; + CCharacterCore m_Predicted; + + CTeeRenderInfo m_SkinInfo; // this is what the server reports + CTeeRenderInfo m_RenderInfo; // this is what we use + + float m_Angle; + + void UpdateRenderInfo(); + }; + + CClientData m_aClients[MAX_CLIENTS]; + + CRenderTools m_RenderTools; + + void OnReset(); + + // hooks + virtual void OnConnected(); + virtual void OnRender(); + virtual void OnInit(); + virtual void OnConsoleInit(); + virtual void OnStateChange(int NewState, int OldState); + virtual void OnMessage(int MsgId, CUnpacker *pUnpacker); + virtual void OnNewSnapshot(); + virtual void OnPredict(); + virtual int OnSnapInput(int *pData); + virtual void OnShutdown(); + virtual void OnEnterGame(); + virtual void OnRconLine(const char *pLine); + + virtual const char *GetItemName(int Type); + virtual const char *Version(); + virtual const char *NetVersion(); + + + // actions + // TODO: move these + void SendSwitchTeam(int Team); + void SendInfo(bool Start); + void SendKill(int ClientId); + + // pointers to all systems + class CGameConsole *m_pGameConsole; + class CBinds *m_pBinds; + class CParticles *m_pParticles; + class CMenus *m_pMenus; + class CSkins *m_pSkins; + class CFlow *m_pFlow; + class CChat *m_pChat; + class CDamageInd *m_pDamageind; + class CCamera *m_pCamera; + class CControls *m_pControls; + class CEffects *m_pEffects; + class CSounds *m_pSounds; + class CMotd *m_pMotd; + class CMapImages *m_pMapimages; + class CVoting *m_pVoting; +}; + +extern const char *Localize(const char *Str); + +#endif diff --git a/src/game/client/gameclient.hpp b/src/game/client/gameclient.hpp deleted file mode 100644 index 1da40de0..00000000 --- a/src/game/client/gameclient.hpp +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef FILE_GAMECLIENT_HPP -#define FILE_GAMECLIENT_HPP - -#include <base/vmath.hpp> -#include <engine/e_console.h> -#include <engine/client/client.h> -#include <game/gamecore.hpp> -#include "render.hpp" - -class GAMECLIENT : public IGameClient -{ - class STACK - { - public: - enum - { - MAX_COMPONENTS = 64, - }; - - STACK(); - void add(class COMPONENT *component); - - class COMPONENT *components[MAX_COMPONENTS]; - int num; - }; - - STACK all; - STACK input; - - class IGraphics *m_pGraphics; - class IEngine *m_pEngine; - CUI m_UI; - - void dispatch_input(); - void process_events(); - void update_local_character_pos(); - - int predicted_tick; - int last_new_predicted_tick; - - static void con_team(void *result, void *user_data); - static void con_kill(void *result, void *user_data); - - static void conchain_special_infoupdate(void *result, void *user_data, CONSOLE_CALLBACK cb, void *cbuser); - -public: - class IGraphics *Graphics() const { return m_pGraphics; } - class CUI *UI() { return &m_UI; } - class CRenderTools *RenderTools() { return &m_RenderTools; } - - void SetEngine(class IEngine *pEngine); - - bool suppress_events; - bool new_tick; - bool new_predicted_tick; - - // TODO: move this - TUNING_PARAMS tuning; - - enum - { - SERVERMODE_PURE=0, - SERVERMODE_MOD, - SERVERMODE_PUREMOD, - }; - int servermode; - - vec2 local_character_pos; - - // predicted players - CHARACTER_CORE predicted_prev_char; - CHARACTER_CORE predicted_char; - - // snap pointers - struct SNAPSTATE - { - const NETOBJ_CHARACTER *local_character; - const NETOBJ_CHARACTER *local_prev_character; - const NETOBJ_PLAYER_INFO *local_info; - const NETOBJ_FLAG *flags[2]; - const NETOBJ_GAME *gameobj; - - const NETOBJ_PLAYER_INFO *player_infos[MAX_CLIENTS]; - const NETOBJ_PLAYER_INFO *info_by_score[MAX_CLIENTS]; - - int local_cid; - int num_players; - int team_size[2]; - bool spectate; - - // - struct CHARACTERINFO - { - bool active; - - // snapshots - NETOBJ_CHARACTER prev; - NETOBJ_CHARACTER cur; - - // interpolated position - vec2 position; - }; - - CHARACTERINFO characters[MAX_CLIENTS]; - }; - - SNAPSTATE snap; - - // client data - struct CLIENT_DATA - { - int use_custom_color; - int color_body; - int color_feet; - - char name[64]; - char skin_name[64]; - int skin_id; - int skin_color; - int team; - int emoticon; - int emoticon_start; - CHARACTER_CORE predicted; - - TEE_RENDER_INFO skin_info; // this is what the server reports - TEE_RENDER_INFO render_info; // this is what we use - - float angle; - - void update_render_info(); - }; - - CLIENT_DATA clients[MAX_CLIENTS]; - - CRenderTools m_RenderTools; - - void on_reset(); - - // hooks - void on_connected(); - void on_render(); - void on_init(); - void on_save(); - void on_console_init(); - void on_statechange(int new_state, int old_state); - void on_message(int msgtype); - void on_snapshot(); - void on_predict(); - int on_snapinput(int *data); - - // actions - // TODO: move these - void send_switch_team(int team); - void send_info(bool start); - void send_kill(int client_id); - - // pointers to all systems - class CONSOLE *console; - class BINDS *binds; - class PARTICLES *particles; - class MENUS *menus; - class SKINS *skins; - class FLOW *flow; - class CHAT *chat; - class DAMAGEIND *damageind; - class CAMERA *camera; - class CONTROLS *controls; - class EFFECTS *effects; - class SOUNDS *sounds; - class MOTD *motd; - class MAPIMAGES *mapimages; - class VOTING *voting; -}; - - -// TODO: Refactor: Remove this -extern GAMECLIENT gameclient; - -extern const char *localize(const char *str); - -#endif diff --git a/src/game/client/lineinput.cpp b/src/game/client/lineinput.cpp index f8c9d7e7..f1159caf 100644 --- a/src/game/client/lineinput.cpp +++ b/src/game/client/lineinput.cpp @@ -1,85 +1,90 @@ -#include <engine/e_client_interface.h> -#include <string.h> // strlen -#include "lineinput.hpp" +#include <engine/keys.h> +#include "lineinput.h" -LINEINPUT::LINEINPUT() +CLineInput::CLineInput() { - clear(); + Clear(); } -void LINEINPUT::clear() +void CLineInput::Clear() { - mem_zero(str, sizeof(str)); - len = 0; - cursor_pos = 0; + mem_zero(m_Str, sizeof(m_Str)); + m_Len = 0; + m_CursorPos = 0; } -void LINEINPUT::set(const char *string) +void CLineInput::Set(const char *pString) { - str_copy(str, string, sizeof(str)); - len = strlen(str); - cursor_pos = len; + str_copy(m_Str, pString, sizeof(m_Str)); + m_Len = str_length(m_Str); + m_CursorPos = m_Len; } -void LINEINPUT::manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len_ptr, int *cursor_pos_ptr) +bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr) { - int cursor_pos = *cursor_pos_ptr; - int len = *str_len_ptr; + int CursorPos = *pCursorPosPtr; + int Len = *pStrLenPtr; + bool Changes = false; - if(cursor_pos > len) - cursor_pos = len; + if(CursorPos > Len) + CursorPos = Len; - int code = e.unicode; - int k = e.key; + int Code = e.m_Unicode; + int k = e.m_Key; // 127 is produced on Mac OS X and corresponds to the delete key - if (!(code >= 0 && code < 32) && code != 127) + if (!(Code >= 0 && Code < 32) && Code != 127) { - char tmp[8]; - int charsize = str_utf8_encode(tmp, code); + char Tmp[8]; + int CharSize = str_utf8_encode(Tmp, Code); - if (len < str_max_size - charsize && cursor_pos < str_max_size - charsize) + if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize) { - memmove(str + cursor_pos + charsize, str + cursor_pos, len - cursor_pos + charsize); - for(int i = 0; i < charsize; i++) - str[cursor_pos+i] = tmp[i]; - cursor_pos += charsize; - len += charsize; + mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len - CursorPos + CharSize); + for(int i = 0; i < CharSize; i++) + pStr[CursorPos+i] = Tmp[i]; + CursorPos += CharSize; + Len += CharSize; + Changes = true; } } - if(e.flags&INPFLAG_PRESS) + if(e.m_Flags&IInput::FLAG_PRESS) { - if (k == KEY_BACKSPACE && cursor_pos > 0) + if (k == KEY_BACKSPACE && CursorPos > 0) { - int new_cursor_pos = str_utf8_rewind(str, cursor_pos); - int charsize = cursor_pos-new_cursor_pos; - memmove(str+new_cursor_pos, str+cursor_pos, len - charsize + 1); // +1 == null term - cursor_pos = new_cursor_pos; - len -= charsize; + int NewCursorPos = str_utf8_rewind(pStr, CursorPos); + int CharSize = CursorPos-NewCursorPos; + mem_move(pStr+NewCursorPos, pStr+CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term + CursorPos = NewCursorPos; + Len -= CharSize; + Changes = true; } - else if (k == KEY_DELETE && cursor_pos < len) + else if (k == KEY_DELETE && CursorPos < Len) { - int p = str_utf8_forward(str, cursor_pos); - int charsize = p-cursor_pos; - memmove(str + cursor_pos, str + cursor_pos + charsize, len - cursor_pos - charsize + 1); // +1 == null term - len -= charsize; + int p = str_utf8_forward(pStr, CursorPos); + int CharSize = p-CursorPos; + mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term + Len -= CharSize; + Changes = true; } - else if (k == KEY_LEFT && cursor_pos > 0) - cursor_pos = str_utf8_rewind(str, cursor_pos); - else if (k == KEY_RIGHT && cursor_pos < len) - cursor_pos = str_utf8_forward(str, cursor_pos); + else if (k == KEY_LEFT && CursorPos > 0) + CursorPos = str_utf8_rewind(pStr, CursorPos); + else if (k == KEY_RIGHT && CursorPos < Len) + CursorPos = str_utf8_forward(pStr, CursorPos); else if (k == KEY_HOME) - cursor_pos = 0; + CursorPos = 0; else if (k == KEY_END) - cursor_pos = len; + CursorPos = Len; } - *cursor_pos_ptr = cursor_pos; - *str_len_ptr = len; + *pCursorPosPtr = CursorPos; + *pStrLenPtr = Len; + + return Changes; } -void LINEINPUT::process_input(INPUT_EVENT e) +void CLineInput::ProcessInput(IInput::CEvent e) { - manipulate(e, str, sizeof(str), &len, &cursor_pos); + Manipulate(e, m_Str, sizeof(m_Str), &m_Len, &m_CursorPos); } diff --git a/src/game/client/lineinput.h b/src/game/client/lineinput.h new file mode 100644 index 00000000..f5c65282 --- /dev/null +++ b/src/game/client/lineinput.h @@ -0,0 +1,31 @@ +#ifndef GAME_CLIENT_LINEINPUT_H +#define GAME_CLIENT_LINEINPUT_H + +#include <engine/input.h> + +// line input helter +class CLineInput +{ + char m_Str[256]; + int m_Len; + int m_CursorPos; +public: + static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr); + + class CCallback + { + public: + virtual ~CCallback() {} + virtual bool Event(IInput::CEvent e) = 0; + }; + + CLineInput(); + void Clear(); + void ProcessInput(IInput::CEvent e); + void Set(const char *pString); + const char *GetString() const { return m_Str; } + int GetLength() const { return m_Len; } + unsigned GetCursorOffset() const { return m_CursorPos; } +}; + +#endif diff --git a/src/game/client/lineinput.hpp b/src/game/client/lineinput.hpp deleted file mode 100644 index 75b2bd1d..00000000 --- a/src/game/client/lineinput.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef GAME_CLIENT_LINEINPUT_H -#define GAME_CLIENT_LINEINPUT_H - -// line input helter -class LINEINPUT -{ - char str[256]; - int len; - int cursor_pos; -public: - static void manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len, int *cursor_pos); - - class CALLBACK - { - public: - virtual ~CALLBACK() {} - virtual bool event(INPUT_EVENT e) = 0; - }; - - LINEINPUT(); - void clear(); - void process_input(INPUT_EVENT e); - void set(const char *string); - const char *get_string() const { return str; } - int get_length() const { return len; } - unsigned cursor_offset() const { return cursor_pos; } -}; - -#endif diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index f271c7d2..ee4dc9d9 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -1,19 +1,19 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <math.h> -#include <base/math.hpp> +#include <base/math.h> -#include <engine/e_client_interface.h> -#include <engine/e_config.h> -#include <engine/client/graphics.h> -#include <game/generated/gc_data.hpp> -#include <game/generated/g_protocol.hpp> -#include <game/layers.hpp> -#include "animstate.hpp" -#include "render.hpp" +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/map.h> +#include <game/generated/client_data.h> +#include <game/generated/protocol.h> +#include <game/layers.h> +#include "animstate.h" +#include "render.h" -static float sprite_w_scale; -static float sprite_h_scale; +static float gs_SpriteWScale; +static float gs_SpriteHScale; /* @@ -36,133 +36,141 @@ static void layershot_end() config.cl_layershot++; }*/ -void CRenderTools::select_sprite(SPRITE *spr, int flags, int sx, int sy) +void CRenderTools::SelectSprite(SPRITE *pSpr, int Flags, int sx, int sy) { - int x = spr->x+sx; - int y = spr->y+sy; - int w = spr->w; - int h = spr->h; - int cx = spr->set->gridx; - int cy = spr->set->gridy; + int x = pSpr->m_X+sx; + int y = pSpr->m_Y+sy; + int w = pSpr->m_W; + int h = pSpr->m_H; + int cx = pSpr->m_pSet->m_Gridx; + int cy = pSpr->m_pSet->m_Gridy; float f = sqrtf(h*h + w*w); - sprite_w_scale = w/f; - sprite_h_scale = h/f; + gs_SpriteWScale = w/f; + gs_SpriteHScale = h/f; float x1 = x/(float)cx; float x2 = (x+w)/(float)cx; float y1 = y/(float)cy; float y2 = (y+h)/(float)cy; - float temp = 0; + float Temp = 0; - if(flags&SPRITE_FLAG_FLIP_Y) + if(Flags&SPRITE_FLAG_FLIP_Y) { - temp = y1; + Temp = y1; y1 = y2; - y2 = temp; + y2 = Temp; } - if(flags&SPRITE_FLAG_FLIP_X) + if(Flags&SPRITE_FLAG_FLIP_X) { - temp = x1; + Temp = x1; x1 = x2; - x2 = temp; + x2 = Temp; } Graphics()->QuadsSetSubset(x1, y1, x2, y2); } -void CRenderTools::select_sprite(int id, int flags, int sx, int sy) +void CRenderTools::SelectSprite(int Id, int Flags, int sx, int sy) { - if(id < 0 || id > data->num_sprites) + if(Id < 0 || Id > g_pData->m_NumSprites) return; - select_sprite(&data->sprites[id], flags, sx, sy); + SelectSprite(&g_pData->m_aSprites[Id], Flags, sx, sy); } -void CRenderTools::draw_sprite(float x, float y, float size) +void CRenderTools::DrawSprite(float x, float y, float Size) { - Graphics()->QuadsDraw(x, y, size*sprite_w_scale, size*sprite_h_scale); + IGraphics::CQuadItem QuadItem(x, y, Size*gs_SpriteWScale, Size*gs_SpriteHScale); + Graphics()->QuadsDraw(&QuadItem, 1); } -void CRenderTools::draw_round_rect_ext(float x, float y, float w, float h, float r, int corners) +void CRenderTools::DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners) { - int num = 8; - for(int i = 0; i < num; i+=2) + IGraphics::CFreeformItem ArrayF[32]; + int NumItems = 0; + int Num = 8; + for(int i = 0; i < Num; i+=2) { - float a1 = i/(float)num * pi/2; - float a2 = (i+1)/(float)num * pi/2; - float a3 = (i+2)/(float)num * pi/2; - float ca1 = cosf(a1); - float ca2 = cosf(a2); - float ca3 = cosf(a3); - float sa1 = sinf(a1); - float sa2 = sinf(a2); - float sa3 = sinf(a3); - - if(corners&1) // TL - Graphics()->QuadsDrawFreeform( + float a1 = i/(float)Num * pi/2; + float a2 = (i+1)/(float)Num * pi/2; + float a3 = (i+2)/(float)Num * pi/2; + float Ca1 = cosf(a1); + float Ca2 = cosf(a2); + float Ca3 = cosf(a3); + float Sa1 = sinf(a1); + float Sa2 = sinf(a2); + float Sa3 = sinf(a3); + + if(Corners&1) // TL + ArrayF[NumItems++] = IGraphics::CFreeformItem( x+r, y+r, - x+(1-ca1)*r, y+(1-sa1)*r, - x+(1-ca3)*r, y+(1-sa3)*r, - x+(1-ca2)*r, y+(1-sa2)*r); + x+(1-Ca1)*r, y+(1-Sa1)*r, + x+(1-Ca3)*r, y+(1-Sa3)*r, + x+(1-Ca2)*r, y+(1-Sa2)*r); - if(corners&2) // TR - Graphics()->QuadsDrawFreeform( + if(Corners&2) // TR + ArrayF[NumItems++] = IGraphics::CFreeformItem( x+w-r, y+r, - x+w-r+ca1*r, y+(1-sa1)*r, - x+w-r+ca3*r, y+(1-sa3)*r, - x+w-r+ca2*r, y+(1-sa2)*r); + x+w-r+Ca1*r, y+(1-Sa1)*r, + x+w-r+Ca3*r, y+(1-Sa3)*r, + x+w-r+Ca2*r, y+(1-Sa2)*r); - if(corners&4) // BL - Graphics()->QuadsDrawFreeform( + if(Corners&4) // BL + ArrayF[NumItems++] = IGraphics::CFreeformItem( x+r, y+h-r, - x+(1-ca1)*r, y+h-r+sa1*r, - x+(1-ca3)*r, y+h-r+sa3*r, - x+(1-ca2)*r, y+h-r+sa2*r); + x+(1-Ca1)*r, y+h-r+Sa1*r, + x+(1-Ca3)*r, y+h-r+Sa3*r, + x+(1-Ca2)*r, y+h-r+Sa2*r); - if(corners&8) // BR - Graphics()->QuadsDrawFreeform( + if(Corners&8) // BR + ArrayF[NumItems++] = IGraphics::CFreeformItem( x+w-r, y+h-r, - x+w-r+ca1*r, y+h-r+sa1*r, - x+w-r+ca3*r, y+h-r+sa3*r, - x+w-r+ca2*r, y+h-r+sa2*r); + x+w-r+Ca1*r, y+h-r+Sa1*r, + x+w-r+Ca3*r, y+h-r+Sa3*r, + x+w-r+Ca2*r, y+h-r+Sa2*r); } - - Graphics()->QuadsDrawTL(x+r, y+r, w-r*2, h-r*2); // center - Graphics()->QuadsDrawTL(x+r, y, w-r*2, r); // top - Graphics()->QuadsDrawTL(x+r, y+h-r, w-r*2, r); // bottom - Graphics()->QuadsDrawTL(x, y+r, r, h-r*2); // left - Graphics()->QuadsDrawTL(x+w-r, y+r, r, h-r*2); // right + Graphics()->QuadsDrawFreeform(ArrayF, NumItems); + + IGraphics::CQuadItem ArrayQ[9]; + NumItems = 0; + ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y+r, w-r*2, h-r*2); // center + ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y, w-r*2, r); // top + ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y+h-r, w-r*2, r); // bottom + ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+r, r, h-r*2); // left + ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w-r, y+r, r, h-r*2); // right - if(!(corners&1)) Graphics()->QuadsDrawTL(x, y, r, r); // TL - if(!(corners&2)) Graphics()->QuadsDrawTL(x+w, y, -r, r); // TR - if(!(corners&4)) Graphics()->QuadsDrawTL(x, y+h, r, -r); // BL - if(!(corners&8)) Graphics()->QuadsDrawTL(x+w, y+h, -r, -r); // BR + if(!(Corners&1)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y, r, r); // TL + if(!(Corners&2)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w, y, -r, r); // TR + if(!(Corners&4)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+h, r, -r); // BL + if(!(Corners&8)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w, y+h, -r, -r); // BR + + Graphics()->QuadsDrawTL(ArrayQ, NumItems); } -void CRenderTools::draw_round_rect(float x, float y, float w, float h, float r) +void CRenderTools::DrawRoundRect(float x, float y, float w, float h, float r) { - draw_round_rect_ext(x,y,w,h,r,0xf); + DrawRoundRectExt(x,y,w,h,r,0xf); } -void CRenderTools::DrawUIRect(const CUIRect *r, vec4 color, int corners, float rounding) +void CRenderTools::DrawUIRect(const CUIRect *r, vec4 Color, int Corners, float Rounding) { Graphics()->TextureSet(-1); // TODO: FIX US Graphics()->QuadsBegin(); - Graphics()->SetColor(color.r, color.g, color.b, color.a); - draw_round_rect_ext(r->x,r->y,r->w,r->h,rounding*UI()->Scale(), corners); + Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a); + DrawRoundRectExt(r->x,r->y,r->w,r->h,Rounding*UI()->Scale(), Corners); Graphics()->QuadsEnd(); } -void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, vec2 dir, vec2 pos) +void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos) { - vec2 direction = dir; - vec2 position = pos; + vec2 Direction = Dir; + vec2 Position = Pos; //Graphics()->TextureSet(data->images[IMAGE_CHAR_DEFAULT].id); - Graphics()->TextureSet(info->texture); + Graphics()->TextureSet(pInfo->m_Texture); // TODO: FIX ME Graphics()->QuadsBegin(); @@ -172,75 +180,79 @@ void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, // second pass we draw the filling for(int p = 0; p < 2; p++) { - int outline = p==0 ? 1 : 0; + int OutLine = p==0 ? 1 : 0; for(int f = 0; f < 2; f++) { - float animscale = info->size * 1.0f/64.0f; - float basesize = info->size; + float AnimScale = pInfo->m_Size * 1.0f/64.0f; + float BaseSize = pInfo->m_Size; if(f == 1) { - Graphics()->QuadsSetRotation(anim->body.angle*pi*2); + Graphics()->QuadsSetRotation(pAnim->GetBody()->m_Angle*pi*2); // draw body - Graphics()->SetColor(info->color_body.r, info->color_body.g, info->color_body.b, 1.0f); - vec2 body_pos = position + vec2(anim->body.x, anim->body.y)*animscale; - select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0); - Graphics()->QuadsDraw(body_pos.x, body_pos.y, basesize, basesize); + Graphics()->SetColor(pInfo->m_ColorBody.r, pInfo->m_ColorBody.g, pInfo->m_ColorBody.b, 1.0f); + vec2 BodyPos = Position + vec2(pAnim->GetBody()->m_X, pAnim->GetBody()->m_Y)*AnimScale; + SelectSprite(OutLine?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0); + IGraphics::CQuadItem QuadItem(BodyPos.x, BodyPos.y, BaseSize, BaseSize); + Graphics()->QuadsDraw(&QuadItem, 1); // draw eyes if(p == 1) { - switch (emote) + switch (Emote) { case EMOTE_PAIN: - select_sprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0); + SelectSprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0); break; case EMOTE_HAPPY: - select_sprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0); + SelectSprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0); break; case EMOTE_SURPRISE: - select_sprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0); + SelectSprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0); break; case EMOTE_ANGRY: - select_sprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0); + SelectSprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0); break; default: - select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0); + SelectSprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0); break; } - float eyescale = basesize*0.40f; - float h = emote == EMOTE_BLINK ? basesize*0.15f : eyescale; - float eyeseparation = (0.075f - 0.010f*fabs(direction.x))*basesize; - vec2 offset = vec2(direction.x*0.125f, -0.05f+direction.y*0.10f)*basesize; - Graphics()->QuadsDraw(body_pos.x-eyeseparation+offset.x, body_pos.y+offset.y, eyescale, h); - Graphics()->QuadsDraw(body_pos.x+eyeseparation+offset.x, body_pos.y+offset.y, -eyescale, h); + float EyeScale = BaseSize*0.40f; + float h = Emote == EMOTE_BLINK ? BaseSize*0.15f : EyeScale; + float EyeSeparation = (0.075f - 0.010f*absolute(Direction.x))*BaseSize; + vec2 Offset = vec2(Direction.x*0.125f, -0.05f+Direction.y*0.10f)*BaseSize; + IGraphics::CQuadItem Array[2] = { + IGraphics::CQuadItem(BodyPos.x-EyeSeparation+Offset.x, BodyPos.y+Offset.y, EyeScale, h), + IGraphics::CQuadItem(BodyPos.x+EyeSeparation+Offset.x, BodyPos.y+Offset.y, -EyeScale, h)}; + Graphics()->QuadsDraw(Array, 2); } } // draw feet - ANIM_KEYFRAME *foot = f ? &anim->front_foot : &anim->back_foot; + ANIM_KEYFRAME *pFoot = f ? pAnim->GetFrontFoot() : pAnim->GetBackFoot(); - float w = basesize; - float h = basesize/2; + float w = BaseSize; + float h = BaseSize/2; - Graphics()->QuadsSetRotation(foot->angle*pi*2); + Graphics()->QuadsSetRotation(pFoot->m_Angle*pi*2); - bool indicate = !info->got_airjump && config.cl_airjumpindicator; + bool Indicate = !pInfo->m_GotAirJump && g_Config.m_ClAirjumpindicator; float cs = 1.0f; // color scale - if(outline) - select_sprite(SPRITE_TEE_FOOT_OUTLINE, 0, 0, 0); + if(OutLine) + SelectSprite(SPRITE_TEE_FOOT_OUTLINE, 0, 0, 0); else { - select_sprite(SPRITE_TEE_FOOT, 0, 0, 0); - if(indicate) + SelectSprite(SPRITE_TEE_FOOT, 0, 0, 0); + if(Indicate) cs = 0.5f; } - Graphics()->SetColor(info->color_feet.r*cs, info->color_feet.g*cs, info->color_feet.b*cs, 1.0f); - Graphics()->QuadsDraw(position.x+foot->x*animscale, position.y+foot->y*animscale, w, h); + Graphics()->SetColor(pInfo->m_ColorFeet.r*cs, pInfo->m_ColorFeet.g*cs, pInfo->m_ColorFeet.b*cs, 1.0f); + IGraphics::CQuadItem QuadItem(Position.x+pFoot->m_X*AnimScale, Position.y+pFoot->m_Y*AnimScale, w, h); + Graphics()->QuadsDraw(&QuadItem, 1); } } @@ -249,67 +261,68 @@ void CRenderTools::RenderTee(ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, } -static void calc_screen_params(float amount, float wmax, float hmax, float aspect, float *w, float *h) +static void CalcScreenParams(float Amount, float WMax, float HMax, float Aspect, float *w, float *h) { - float f = sqrt(amount) / sqrt(aspect); - *w = f*aspect; + float f = sqrtf(Amount) / sqrtf(Aspect); + *w = f*Aspect; *h = f; // limit the view - if(*w > wmax) + if(*w > WMax) { - *w = wmax; - *h = *w/aspect; + *w = WMax; + *h = *w/Aspect; } - if(*h > hmax) + if(*h > HMax) { - *h = hmax; - *w = *h*aspect; + *h = HMax; + *w = *h*Aspect; } } -void CRenderTools::mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y, - float offset_x, float offset_y, float aspect, float zoom, float *points) +void CRenderTools::MapscreenToWorld(float CenterX, float CenterY, float ParallaxX, float ParallaxY, + float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints) { - float width, height; - calc_screen_params(1150*1000, 1500, 1050, aspect, &width, &height); - center_x *= parallax_x; - center_y *= parallax_y; - width *= zoom; - height *= zoom; - points[0] = offset_x+center_x-width/2; - points[1] = offset_y+center_y-height/2; - points[2] = offset_x+center_x+width/2; - points[3] = offset_y+center_y+height/2; + float Width, Height; + CalcScreenParams(1150*1000, 1500, 1050, Aspect, &Width, &Height); + CenterX *= ParallaxX; + CenterY *= ParallaxY; + Width *= Zoom; + Height *= Zoom; + pPoints[0] = OffsetX+CenterX-Width/2; + pPoints[1] = OffsetY+CenterY-Height/2; + pPoints[2] = OffsetX+CenterX+Width/2; + pPoints[3] = OffsetY+CenterY+Height/2; } -void CRenderTools::render_tilemap_generate_skip() +void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) { - for(int g = 0; g < layers_num_groups(); g++) + + for(int g = 0; g < pLayers->NumGroups(); g++) { - MAPITEM_GROUP *group = layers_get_group(g); + CMapItemGroup *pGroup = pLayers->GetGroup(g); - for(int l = 0; l < group->num_layers; l++) + for(int l = 0; l < pGroup->m_NumLayers; l++) { - MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l); + CMapItemLayer *pLayer = pLayers->GetLayer(pGroup->m_StartLayer+l); - if(layer->type == LAYERTYPE_TILES) + if(pLayer->m_Type == LAYERTYPE_TILES) { - MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer; - TILE *tiles = (TILE *)map_get_data(tmap->data); - for(int y = 0; y < tmap->height; y++) + CMapItemLayerTilemap *pTmap = (CMapItemLayerTilemap *)pLayer; + CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data); + for(int y = 0; y < pTmap->m_Height; y++) { - for(int x = 1; x < tmap->width; x++) + for(int x = 1; x < pTmap->m_Width; x++) { int sx; - for(sx = 1; x+sx < tmap->width && sx < 255; sx++) + for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++) { - if(tiles[y*tmap->width+x+sx].index) + if(pTiles[y*pTmap->m_Width+x+sx].m_Index) break; } - tiles[y*tmap->width+x].skip = sx-1; + pTiles[y*pTmap->m_Width+x].m_Skip = sx-1; } } } diff --git a/src/game/client/render.h b/src/game/client/render.h new file mode 100644 index 00000000..a546b3eb --- /dev/null +++ b/src/game/client/render.h @@ -0,0 +1,79 @@ +#ifndef GAME_CLIENT_RENDER_H +#define GAME_CLIENT_RENDER_H + +#include <base/vmath.h> +#include <game/mapitems.h> +#include "ui.h" + + +struct CTeeRenderInfo +{ + CTeeRenderInfo() + { + m_Texture = -1; + m_ColorBody = vec4(1,1,1,1); + m_ColorFeet = vec4(1,1,1,1); + m_Size = 1.0f; + m_GotAirJump = 1; + }; + + int m_Texture; + vec4 m_ColorBody; + vec4 m_ColorFeet; + float m_Size; + int m_GotAirJump; +}; + +// sprite renderings +enum +{ + SPRITE_FLAG_FLIP_Y=1, + SPRITE_FLAG_FLIP_X=2, + + LAYERRENDERFLAG_OPAQUE=1, + LAYERRENDERFLAG_TRANSPARENT=2, + + TILERENDERFLAG_EXTEND=4, +}; + + +class CRenderTools +{ +public: + class IGraphics *m_pGraphics; + class CUI *m_pUI; + + class IGraphics *Graphics() const { return m_pGraphics; } + class CUI *UI() const { return m_pUI; } + + //typedef struct SPRITE; + + void SelectSprite(struct SPRITE *pSprite, int Flags=0, int sx=0, int sy=0); + void SelectSprite(int id, int Flags=0, int sx=0, int sy=0); + + void DrawSprite(float x, float y, float size); + + // rects + void DrawRoundRect(float x, float y, float w, float h, float r); + void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners); + + void DrawUIRect(const CUIRect *pRect, vec4 Color, int Corners, float Rounding); + + // larger rendering methods + void RenderTilemapGenerateSkip(class CLayers *pLayers); + + // object render methods (gc_render_obj.cpp) + void RenderTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos); + + // map render methods (gc_render_map.cpp) + static void RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult); + void RenderQuads(CQuad *pQuads, int NumQuads, int Flags, void (*pfnEval)(float TimeOffset, int Env, float *pChannels, void *pUser), void *pUser); + void RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Color, int Flags); + + // helpers + void MapscreenToWorld(float CenterX, float CenterY, float ParallaxX, float ParallaxY, + float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints); + +}; + +#endif diff --git a/src/game/client/render.hpp b/src/game/client/render.hpp deleted file mode 100644 index 8e99b432..00000000 --- a/src/game/client/render.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#ifndef GAME_CLIENT_RENDER_H -#define GAME_CLIENT_RENDER_H - -#include <base/vmath.hpp> - -#include "../mapitems.hpp" -#include "ui.hpp" - - -struct TEE_RENDER_INFO -{ - TEE_RENDER_INFO() - { - texture = -1; - color_body = vec4(1,1,1,1); - color_feet = vec4(1,1,1,1); - size = 1.0f; - got_airjump = 1; - }; - - int texture; - vec4 color_body; - vec4 color_feet; - float size; - int got_airjump; -}; - -// sprite renderings -enum -{ - SPRITE_FLAG_FLIP_Y=1, - SPRITE_FLAG_FLIP_X=2, - - LAYERRENDERFLAG_OPAQUE=1, - LAYERRENDERFLAG_TRANSPARENT=2, - - TILERENDERFLAG_EXTEND=4, -}; - - -class CRenderTools -{ -public: - class IGraphics *m_pGraphics; - class CUI *m_pUI; - - class IGraphics *Graphics() const { return m_pGraphics; } - class CUI *UI() const { return m_pUI; } - - //typedef struct SPRITE; - - void select_sprite(struct SPRITE *spr, int flags=0, int sx=0, int sy=0); - void select_sprite(int id, int flags=0, int sx=0, int sy=0); - - void draw_sprite(float x, float y, float size); - - // rects - void draw_round_rect(float x, float y, float w, float h, float r); - void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners); - - void DrawUIRect(const CUIRect *r, vec4 color, int corners, float rounding); - - // larger rendering methods - void render_tilemap_generate_skip(); - - // object render methods (gc_render_obj.cpp) - void RenderTee(class ANIMSTATE *anim, TEE_RENDER_INFO *info, int emote, vec2 dir, vec2 pos); - - // map render methods (gc_render_map.cpp) - static void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result); - void render_quads(QUAD *quads, int num_quads, int flags, void (*eval)(float time_offset, int env, float *channels, void *user), void *user); - void render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int flags); - - // helpers - void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y, - float offset_x, float offset_y, float aspect, float zoom, float *points); - -}; - -#endif diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp index ea3b8420..0354b9d5 100644 --- a/src/game/client/render_map.cpp +++ b/src/game/client/render_map.cpp @@ -1,198 +1,198 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <math.h> -#include <base/math.hpp> -#include <engine/e_client_interface.h> -#include <engine/client/graphics.h> +#include <base/math.h> +#include <engine/graphics.h> -#include "render.hpp" +#include "render.h" -void CRenderTools::render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result) +void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult) { - if(num_points == 0) + if(NumPoints == 0) { - result[0] = 0; - result[1] = 0; - result[2] = 0; - result[3] = 0; + pResult[0] = 0; + pResult[1] = 0; + pResult[2] = 0; + pResult[3] = 0; return; } - if(num_points == 1) + if(NumPoints == 1) { - result[0] = fx2f(points[0].values[0]); - result[1] = fx2f(points[0].values[1]); - result[2] = fx2f(points[0].values[2]); - result[3] = fx2f(points[0].values[3]); + pResult[0] = fx2f(pPoints[0].m_aValues[0]); + pResult[1] = fx2f(pPoints[0].m_aValues[1]); + pResult[2] = fx2f(pPoints[0].m_aValues[2]); + pResult[3] = fx2f(pPoints[0].m_aValues[3]); return; } - time = fmod(time, points[num_points-1].time/1000.0f)*1000.0f; - for(int i = 0; i < num_points-1; i++) + Time = fmod(Time, pPoints[NumPoints-1].m_Time/1000.0f)*1000.0f; + for(int i = 0; i < NumPoints-1; i++) { - if(time >= points[i].time && time <= points[i+1].time) + if(Time >= pPoints[i].m_Time && Time <= pPoints[i+1].m_Time) { - float delta = points[i+1].time-points[i].time; - float a = (time-points[i].time)/delta; + float Delta = pPoints[i+1].m_Time-pPoints[i].m_Time; + float a = (Time-pPoints[i].m_Time)/Delta; - if(points[i].curvetype == CURVETYPE_SMOOTH) + if(pPoints[i].m_Curvetype == CURVETYPE_SMOOTH) a = -2*a*a*a + 3*a*a; // second hermite basis - else if(points[i].curvetype == CURVETYPE_SLOW) + else if(pPoints[i].m_Curvetype == CURVETYPE_SLOW) a = a*a*a; - else if(points[i].curvetype == CURVETYPE_FAST) + else if(pPoints[i].m_Curvetype == CURVETYPE_FAST) { a = 1-a; a = 1-a*a*a; } - else if (points[i].curvetype == CURVETYPE_STEP) + else if (pPoints[i].m_Curvetype == CURVETYPE_STEP) a = 0; else { // linear } - for(int c = 0; c < channels; c++) + for(int c = 0; c < Channels; c++) { - float v0 = fx2f(points[i].values[c]); - float v1 = fx2f(points[i+1].values[c]); - result[c] = v0 + (v1-v0) * a; + float v0 = fx2f(pPoints[i].m_aValues[c]); + float v1 = fx2f(pPoints[i+1].m_aValues[c]); + pResult[c] = v0 + (v1-v0) * a; } return; } } - result[0] = fx2f(points[num_points-1].values[0]); - result[1] = fx2f(points[num_points-1].values[1]); - result[2] = fx2f(points[num_points-1].values[2]); - result[3] = fx2f(points[num_points-1].values[3]); + pResult[0] = fx2f(pPoints[NumPoints-1].m_aValues[0]); + pResult[1] = fx2f(pPoints[NumPoints-1].m_aValues[1]); + pResult[2] = fx2f(pPoints[NumPoints-1].m_aValues[2]); + pResult[3] = fx2f(pPoints[NumPoints-1].m_aValues[3]); return; } -static void rotate(POINT *center, POINT *point, float rotation) +static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation) { - int x = point->x - center->x; - int y = point->y - center->y; - point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x); - point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y); + int x = pPoint->x - pCenter->x; + int y = pPoint->y - pCenter->y; + pPoint->x = (int)(x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x); + pPoint->y = (int)(x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y); } -void CRenderTools::render_quads(QUAD *quads, int num_quads, int renderflags, void (*eval)(float time_offset, int env, float *channels, void *user), void *user) +void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, void (*pfnEval)(float TimeOffset, int Env, float *pChannels, void *pUser), void *pUser) { Graphics()->QuadsBegin(); - float conv = 1/255.0f; - for(int i = 0; i < num_quads; i++) + float Conv = 1/255.0f; + for(int i = 0; i < NumQuads; i++) { - QUAD *q = &quads[i]; + CQuad *q = &pQuads[i]; float r=1, g=1, b=1, a=1; - if(q->color_env >= 0) + if(q->m_ColorEnv >= 0) { - float channels[4]; - eval(q->color_env_offset/1000.0f, q->color_env, channels, user); - r = channels[0]; - g = channels[1]; - b = channels[2]; - a = channels[3]; + float aChannels[4]; + pfnEval(q->m_ColorEnvOffset/1000.0f, q->m_ColorEnv, aChannels, pUser); + r = aChannels[0]; + g = aChannels[1]; + b = aChannels[2]; + a = aChannels[3]; } - bool opaque = false; - if(a < 0.01f || (q->colors[0].a < 0.01f && q->colors[1].a < 0.01f && q->colors[2].a < 0.01f && q->colors[3].a < 0.01f)) - opaque = true; + bool Opaque = false; + if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f)) + Opaque = true; - if(opaque && !(renderflags&LAYERRENDERFLAG_OPAQUE)) + if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE)) continue; - if(!opaque && !(renderflags&LAYERRENDERFLAG_TRANSPARENT)) + if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT)) continue; Graphics()->QuadsSetSubsetFree( - fx2f(q->texcoords[0].x), fx2f(q->texcoords[0].y), - fx2f(q->texcoords[1].x), fx2f(q->texcoords[1].y), - fx2f(q->texcoords[2].x), fx2f(q->texcoords[2].y), - fx2f(q->texcoords[3].x), fx2f(q->texcoords[3].y) + fx2f(q->m_aTexcoords[0].x), fx2f(q->m_aTexcoords[0].y), + fx2f(q->m_aTexcoords[1].x), fx2f(q->m_aTexcoords[1].y), + fx2f(q->m_aTexcoords[2].x), fx2f(q->m_aTexcoords[2].y), + fx2f(q->m_aTexcoords[3].x), fx2f(q->m_aTexcoords[3].y) ); - float offset_x = 0; - float offset_y = 0; - float rot = 0; + float OffsetX = 0; + float OffsetY = 0; + float Rot = 0; // TODO: fix this - if(q->pos_env >= 0) + if(q->m_PosEnv >= 0) { - float channels[4]; - eval(q->pos_env_offset/1000.0f, q->pos_env, channels, user); - offset_x = channels[0]; - offset_y = channels[1]; - rot = channels[2]/360.0f*pi*2; + float aChannels[4]; + pfnEval(q->m_PosEnvOffset/1000.0f, q->m_PosEnv, aChannels, pUser); + OffsetX = aChannels[0]; + OffsetY = aChannels[1]; + Rot = aChannels[2]/360.0f*pi*2; } - - Graphics()->SetColorVertex(0, q->colors[0].r*conv*r, q->colors[0].g*conv*g, q->colors[0].b*conv*b, q->colors[0].a*conv*a); - Graphics()->SetColorVertex(1, q->colors[1].r*conv*r, q->colors[1].g*conv*g, q->colors[1].b*conv*b, q->colors[1].a*conv*a); - Graphics()->SetColorVertex(2, q->colors[2].r*conv*r, q->colors[2].g*conv*g, q->colors[2].b*conv*b, q->colors[2].a*conv*a); - Graphics()->SetColorVertex(3, q->colors[3].r*conv*r, q->colors[3].g*conv*g, q->colors[3].b*conv*b, q->colors[3].a*conv*a); + IGraphics::CColorVertex Array[4] = { + IGraphics::CColorVertex(0, q->m_aColors[0].r*Conv*r, q->m_aColors[0].g*Conv*g, q->m_aColors[0].b*Conv*b, q->m_aColors[0].a*Conv*a), + IGraphics::CColorVertex(1, q->m_aColors[1].r*Conv*r, q->m_aColors[1].g*Conv*g, q->m_aColors[1].b*Conv*b, q->m_aColors[1].a*Conv*a), + IGraphics::CColorVertex(2, q->m_aColors[2].r*Conv*r, q->m_aColors[2].g*Conv*g, q->m_aColors[2].b*Conv*b, q->m_aColors[2].a*Conv*a), + IGraphics::CColorVertex(3, q->m_aColors[3].r*Conv*r, q->m_aColors[3].g*Conv*g, q->m_aColors[3].b*Conv*b, q->m_aColors[3].a*Conv*a)}; + Graphics()->SetColorVertex(Array, 4); - POINT *points = q->points; + CPoint *pPoints = q->m_aPoints; - if(rot != 0) + if(Rot != 0) { - static POINT rotated[4]; - rotated[0] = q->points[0]; - rotated[1] = q->points[1]; - rotated[2] = q->points[2]; - rotated[3] = q->points[3]; - points = rotated; + static CPoint aRotated[4]; + aRotated[0] = q->m_aPoints[0]; + aRotated[1] = q->m_aPoints[1]; + aRotated[2] = q->m_aPoints[2]; + aRotated[3] = q->m_aPoints[3]; + pPoints = aRotated; - rotate(&q->points[4], &rotated[0], rot); - rotate(&q->points[4], &rotated[1], rot); - rotate(&q->points[4], &rotated[2], rot); - rotate(&q->points[4], &rotated[3], rot); + Rotate(&q->m_aPoints[4], &aRotated[0], Rot); + Rotate(&q->m_aPoints[4], &aRotated[1], Rot); + Rotate(&q->m_aPoints[4], &aRotated[2], Rot); + Rotate(&q->m_aPoints[4], &aRotated[3], Rot); } - Graphics()->QuadsDrawFreeform( - fx2f(points[0].x)+offset_x, fx2f(points[0].y)+offset_y, - fx2f(points[1].x)+offset_x, fx2f(points[1].y)+offset_y, - fx2f(points[2].x)+offset_x, fx2f(points[2].y)+offset_y, - fx2f(points[3].x)+offset_x, fx2f(points[3].y)+offset_y - ); + IGraphics::CFreeformItem Freeform( + fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY, + fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY, + fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY, + fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY); + Graphics()->QuadsDrawFreeform(&Freeform, 1); } Graphics()->QuadsEnd(); } -void CRenderTools::render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int renderflags) +void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Color, int RenderFlags) { //Graphics()->TextureSet(img_get(tmap->image)); - float screen_x0, screen_y0, screen_x1, screen_y1; - Graphics()->GetScreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1); + float ScreenX0, ScreenY0, ScreenX1, ScreenY1; + Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); //Graphics()->MapScreen(screen_x0-50, screen_y0-50, screen_x1+50, screen_y1+50); // calculate the final pixelsize for the tiles - float tile_pixelsize = 1024/32.0f; - float final_tilesize = scale/(screen_x1-screen_x0) * Graphics()->ScreenWidth(); - float final_tilesize_scale = final_tilesize/tile_pixelsize; + float TilePixelSize = 1024/32.0f; + float FinalTileSize = Scale/(ScreenX1-ScreenX0) * Graphics()->ScreenWidth(); + float FinalTilesetScale = FinalTileSize/TilePixelSize; Graphics()->QuadsBegin(); - Graphics()->SetColor(color.r, color.g, color.b, color.a); + Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a); - int starty = (int)(screen_y0/scale)-1; - int startx = (int)(screen_x0/scale)-1; - int endy = (int)(screen_y1/scale)+1; - int endx = (int)(screen_x1/scale)+1; + int StartY = (int)(ScreenY0/Scale)-1; + int StartX = (int)(ScreenX0/Scale)-1; + int EndY = (int)(ScreenY1/Scale)+1; + int EndX = (int)(ScreenX1/Scale)+1; // adjust the texture shift according to mipmap level - float texsize = 1024.0f; - float frac = (1.25f/texsize) * (1/final_tilesize_scale); - float nudge = (0.5f/texsize) * (1/final_tilesize_scale); + float TexSize = 1024.0f; + float Frac = (1.25f/TexSize) * (1/FinalTilesetScale); + float Nudge = (0.5f/TexSize) * (1/FinalTilesetScale); - for(int y = starty; y < endy; y++) - for(int x = startx; x < endx; x++) + for(int y = StartY; y < EndY; y++) + for(int x = StartX; x < EndX; x++) { int mx = x; int my = y; - if(renderflags&TILERENDERFLAG_EXTEND) + if(RenderFlags&TILERENDERFLAG_EXTEND) { if(mx<0) mx = 0; @@ -217,59 +217,60 @@ void CRenderTools::render_tilemap(TILE *tiles, int w, int h, float scale, vec4 c int c = mx + my*w; - unsigned char index = tiles[c].index; - if(index) + unsigned char Index = pTiles[c].m_Index; + if(Index) { - unsigned char flags = tiles[c].flags; + unsigned char Flags = pTiles[c].m_Flags; - bool render = false; - if(flags&TILEFLAG_OPAQUE) + bool Render = false; + if(Flags&TILEFLAG_OPAQUE) { - if(renderflags&LAYERRENDERFLAG_OPAQUE) - render = true; + if(RenderFlags&LAYERRENDERFLAG_OPAQUE) + Render = true; } else { - if(renderflags&LAYERRENDERFLAG_TRANSPARENT) - render = true; + if(RenderFlags&LAYERRENDERFLAG_TRANSPARENT) + Render = true; } - if(render) + if(Render) { - int tx = index%16; - int ty = index/16; - int px0 = tx*(1024/16); - int py0 = ty*(1024/16); - int px1 = (tx+1)*(1024/16)-1; - int py1 = (ty+1)*(1024/16)-1; + int tx = Index%16; + int ty = Index/16; + int Px0 = tx*(1024/16); + int Py0 = ty*(1024/16); + int Px1 = (tx+1)*(1024/16)-1; + int Py1 = (ty+1)*(1024/16)-1; - float u0 = nudge + px0/texsize+frac; - float v0 = nudge + py0/texsize+frac; - float u1 = nudge + px1/texsize-frac; - float v1 = nudge + py1/texsize-frac; + float u0 = Nudge + Px0/TexSize+Frac; + float v0 = Nudge + Py0/TexSize+Frac; + float u1 = Nudge + Px1/TexSize-Frac; + float v1 = Nudge + Py1/TexSize-Frac; - if(flags&TILEFLAG_VFLIP) + if(Flags&TILEFLAG_VFLIP) { - float tmp = u0; + float Tmp = u0; u0 = u1; - u1 = tmp; + u1 = Tmp; } - if(flags&TILEFLAG_HFLIP) + if(Flags&TILEFLAG_HFLIP) { - float tmp = v0; + float Tmp = v0; v0 = v1; - v1 = tmp; + v1 = Tmp; } Graphics()->QuadsSetSubset(u0,v0,u1,v1); - Graphics()->QuadsDrawTL(x*scale, y*scale, scale, scale); + IGraphics::CQuadItem QuadItem(x*Scale, y*Scale, Scale, Scale); + Graphics()->QuadsDrawTL(&QuadItem, 1); } } - x += tiles[c].skip; + x += pTiles[c].m_Skip; } Graphics()->QuadsEnd(); - Graphics()->MapScreen(screen_x0, screen_y0, screen_x1, screen_y1); + Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 4aaaf32f..2895b717 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -1,10 +1,10 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <base/system.h> -#include <engine/e_client_interface.h> -#include <engine/e_config.h> -#include <engine/client/graphics.h> -#include "ui.hpp" +#include <engine/shared/config.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include "ui.h" /******************************************************** UI @@ -30,12 +30,12 @@ CUI::CUI() m_Screen.h = 480.0f; } -int CUI::Update(float mx, float my, float mwx, float mwy, int Buttons) +int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) { - m_MouseX = mx; - m_MouseY = my; - m_MouseWorldX = mwx; - m_MouseWorldY = mwy; + m_MouseX = Mx; + m_MouseY = My; + m_MouseWorldX = Mwx; + m_MouseWorldY = Mwy; m_LastMouseButtons = m_MouseButtons; m_MouseButtons = Buttons; m_pHotItem = m_pBecommingHotItem; @@ -54,11 +54,11 @@ int CUI::MouseInside(const CUIRect *r) CUIRect *CUI::Screen() { - float aspect = Graphics()->ScreenAspect(); + float Aspect = Graphics()->ScreenAspect(); float w, h; h = 600; - w = aspect*h; + w = Aspect*h; m_Screen.w = w; m_Screen.h = h; @@ -78,9 +78,9 @@ void CUI::SetScale(float s) void CUI::ClipEnable(const CUIRect *r) { - float xscale = Graphics()->ScreenWidth()/Screen()->w; - float yscale = Graphics()->ScreenHeight()/Screen()->h; - Graphics()->ClipEnable((int)(r->x*xscale), (int)(r->y*yscale), (int)(r->w*xscale), (int)(r->h*yscale)); + float XScale = Graphics()->ScreenWidth()/Screen()->w; + float YScale = Graphics()->ScreenHeight()/Screen()->h; + Graphics()->ClipEnable((int)(r->x*XScale), (int)(r->y*YScale), (int)(r->w*XScale), (int)(r->h*YScale)); } void CUI::ClipDisable() @@ -88,153 +88,153 @@ void CUI::ClipDisable() Graphics()->ClipDisable(); } -void CUIRect::HSplitTop(float cut, CUIRect *top, CUIRect *bottom) const +void CUIRect::HSplitTop(float Cut, CUIRect *pTop, CUIRect *pBottom) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - if (top) + if (pTop) { - top->x = r.x; - top->y = r.y; - top->w = r.w; - top->h = cut; + pTop->x = r.x; + pTop->y = r.y; + pTop->w = r.w; + pTop->h = Cut; } - if (bottom) + if (pBottom) { - bottom->x = r.x; - bottom->y = r.y + cut; - bottom->w = r.w; - bottom->h = r.h - cut; + pBottom->x = r.x; + pBottom->y = r.y + Cut; + pBottom->w = r.w; + pBottom->h = r.h - Cut; } } -void CUIRect::HSplitBottom(float cut, CUIRect *top, CUIRect *bottom) const +void CUIRect::HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - if (top) + if (pTop) { - top->x = r.x; - top->y = r.y; - top->w = r.w; - top->h = r.h - cut; + pTop->x = r.x; + pTop->y = r.y; + pTop->w = r.w; + pTop->h = r.h - Cut; } - if (bottom) + if (pBottom) { - bottom->x = r.x; - bottom->y = r.y + r.h - cut; - bottom->w = r.w; - bottom->h = cut; + pBottom->x = r.x; + pBottom->y = r.y + r.h - Cut; + pBottom->w = r.w; + pBottom->h = Cut; } } -void CUIRect::VSplitMid(CUIRect *left, CUIRect *right) const +void CUIRect::VSplitMid(CUIRect *pLeft, CUIRect *pRight) const { CUIRect r = *this; - float cut = r.w/2; + float Cut = r.w/2; - if (left) + if (pLeft) { - left->x = r.x; - left->y = r.y; - left->w = cut; - left->h = r.h; + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = Cut; + pLeft->h = r.h; } - if (right) + if (pRight) { - right->x = r.x + cut; - right->y = r.y; - right->w = r.w - cut; - right->h = r.h; + pRight->x = r.x + Cut; + pRight->y = r.y; + pRight->w = r.w - Cut; + pRight->h = r.h; } } -void CUIRect::VSplitLeft(float cut, CUIRect *left, CUIRect *right) const +void CUIRect::VSplitLeft(float Cut, CUIRect *pLeft, CUIRect *pRight) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - if (left) + if (pLeft) { - left->x = r.x; - left->y = r.y; - left->w = cut; - left->h = r.h; + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = Cut; + pLeft->h = r.h; } - if (right) + if (pRight) { - right->x = r.x + cut; - right->y = r.y; - right->w = r.w - cut; - right->h = r.h; + pRight->x = r.x + Cut; + pRight->y = r.y; + pRight->w = r.w - Cut; + pRight->h = r.h; } } -void CUIRect::VSplitRight(float cut, CUIRect *left, CUIRect *right) const +void CUIRect::VSplitRight(float Cut, CUIRect *pLeft, CUIRect *pRight) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - if (left) + if (pLeft) { - left->x = r.x; - left->y = r.y; - left->w = r.w - cut; - left->h = r.h; + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = r.w - Cut; + pLeft->h = r.h; } - if (right) + if (pRight) { - right->x = r.x + r.w - cut; - right->y = r.y; - right->w = cut; - right->h = r.h; + pRight->x = r.x + r.w - Cut; + pRight->y = r.y; + pRight->w = Cut; + pRight->h = r.h; } } -void CUIRect::Margin(float cut, CUIRect *other_rect) const +void CUIRect::Margin(float Cut, CUIRect *pOtherRect) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - other_rect->x = r.x + cut; - other_rect->y = r.y + cut; - other_rect->w = r.w - 2*cut; - other_rect->h = r.h - 2*cut; + pOtherRect->x = r.x + Cut; + pOtherRect->y = r.y + Cut; + pOtherRect->w = r.w - 2*Cut; + pOtherRect->h = r.h - 2*Cut; } -void CUIRect::VMargin(float cut, CUIRect *other_rect) const +void CUIRect::VMargin(float Cut, CUIRect *pOtherRect) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - other_rect->x = r.x + cut; - other_rect->y = r.y; - other_rect->w = r.w - 2*cut; - other_rect->h = r.h; + pOtherRect->x = r.x + Cut; + pOtherRect->y = r.y; + pOtherRect->w = r.w - 2*Cut; + pOtherRect->h = r.h; } -void CUIRect::HMargin(float cut, CUIRect *other_rect) const +void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const { CUIRect r = *this; - cut *= Scale(); + Cut *= Scale(); - other_rect->x = r.x; - other_rect->y = r.y + cut; - other_rect->w = r.w; - other_rect->h = r.h - 2*cut; + pOtherRect->x = r.x; + pOtherRect->y = r.y + Cut; + pOtherRect->w = r.w; + pOtherRect->h = r.h - 2*Cut; } int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - /* logic */ + // logic int ReturnValue = 0; int Inside = MouseInside(pRect); static int ButtonUsed = 0; @@ -308,21 +308,21 @@ int CUI::DoButton(const void *id, const char *text, int checked, const CUIRect * return ret; }*/ -void CUI::DoLabel(const CUIRect *r, const char *text, float size, int align, int max_width) +void CUI::DoLabel(const CUIRect *r, const char *pText, float size, int Align, int MaxWidth) { // TODO: FIX ME!!!! //Graphics()->BlendNormal(); size *= Scale(); - if(align == 0) + if(Align == 0) { - float tw = gfx_text_width(0, size, text, max_width); - gfx_text(0, r->x + r->w/2-tw/2, r->y, size, text, max_width); + float tw = TextRender()->TextWidth(0, size, pText, MaxWidth); + TextRender()->Text(0, r->x + r->w/2-tw/2, r->y - size/10, size, pText, MaxWidth); } - else if(align < 0) - gfx_text(0, r->x, r->y, size, text, max_width); - else if(align > 0) + else if(Align < 0) + TextRender()->Text(0, r->x, r->y - size/10, size, pText, MaxWidth); + else if(Align > 0) { - float tw = gfx_text_width(0, size, text, max_width); - gfx_text(0, r->x + r->w-tw, r->y, size, text, max_width); + float tw = TextRender()->TextWidth(0, size, pText, MaxWidth); + TextRender()->Text(0, r->x + r->w-tw, r->y - size/10, size, pText, MaxWidth); } } diff --git a/src/game/client/ui.hpp b/src/game/client/ui.h index 96f6c48b..e88b0e39 100644 --- a/src/game/client/ui.hpp +++ b/src/game/client/ui.h @@ -1,6 +1,5 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#ifndef FILE_GAME_CLIENT_UI_H -#define FILE_GAME_CLIENT_UI_H +#ifndef GAME_CLIENT_UI_H +#define GAME_CLIENT_UI_H class CUIRect { @@ -27,18 +26,20 @@ class CUI const void *m_pActiveItem; const void *m_pLastActiveItem; const void *m_pBecommingHotItem; - float m_MouseX, m_MouseY; /* in gui space */ - float m_MouseWorldX, m_MouseWorldY; /* in world space */ + float m_MouseX, m_MouseY; // in gui space + float m_MouseWorldX, m_MouseWorldY; // in world space unsigned m_MouseButtons; unsigned m_LastMouseButtons; CUIRect m_Screen; class IGraphics *m_pGraphics; + class ITextRender *m_pTextRender; public: // TODO: Refactor: Fill this in - void SetGraphics(class IGraphics *pGraphics) { m_pGraphics = pGraphics; } + void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pGraphics = pGraphics; m_pTextRender = pTextRender;} class IGraphics *Graphics() { return m_pGraphics; } + class ITextRender *TextRender() { return m_pTextRender; } CUI(); @@ -57,7 +58,7 @@ public: CORNER_ALL=CORNER_T|CORNER_B }; - int Update(float mx, float my, float mwx, float mwy, int buttons); + int Update(float mx, float my, float Mwx, float Mwy, int m_Buttons); float MouseX() const { return m_MouseX; } float MouseY() const { return m_MouseY; } @@ -74,10 +75,10 @@ public: const void *ActiveItem() const { return m_pActiveItem; } const void *LastActiveItem() const { return m_pLastActiveItem; } - int MouseInside(const CUIRect *r); + int MouseInside(const CUIRect *pRect); CUIRect *Screen(); - void ClipEnable(const CUIRect *r); + void ClipEnable(const CUIRect *pRect); void ClipDisable(); // TODO: Refactor: Redo UI scaling @@ -87,7 +88,7 @@ public: int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); // TODO: Refactor: Remove this? - void DoLabel(const CUIRect *r, const char *text, float size, int align, int max_width = -1); + void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1); }; diff --git a/src/game/collision.cpp b/src/game/collision.cpp index 73f4a9c5..0dee57c8 100644 --- a/src/game/collision.cpp +++ b/src/game/collision.cpp @@ -1,87 +1,202 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <base/system.h> -#include <base/math.hpp> -#include <base/vmath.hpp> +#include <base/math.h> +#include <base/vmath.h> #include <math.h> -#include <engine/e_common_interface.h> -#include <game/mapitems.hpp> -#include <game/layers.hpp> -#include <game/collision.hpp> +#include <engine/map.h> +#include <engine/kernel.h> -static TILE *tiles; -static int width = 0; -static int height = 0; +#include <game/mapitems.h> +#include <game/layers.h> +#include <game/collision.h> -int col_width() { return width; } -int col_height() { return height; } +CCollision::CCollision() +{ + m_pTiles = 0; + m_Width = 0; + m_Height = 0; + m_pLayers = 0; +} -int col_init() +void CCollision::Init(class CLayers *pLayers) { - width = layers_game_layer()->width; - height = layers_game_layer()->height; - tiles = (TILE *)map_get_data(layers_game_layer()->data); + m_pLayers = pLayers; + m_Width = m_pLayers->GameLayer()->m_Width; + m_Height = m_pLayers->GameLayer()->m_Height; + m_pTiles = static_cast<CTile *>(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data)); - for(int i = 0; i < width*height; i++) + for(int i = 0; i < m_Width*m_Height; i++) { - int index = tiles[i].index; + int Index = m_pTiles[i].m_Index; - if(index > 128) + if(Index > 128) continue; - if(index == TILE_DEATH) - tiles[i].index = COLFLAG_DEATH; - else if(index == TILE_SOLID) - tiles[i].index = COLFLAG_SOLID; - else if(index == TILE_NOHOOK) - tiles[i].index = COLFLAG_SOLID|COLFLAG_NOHOOK; - else - tiles[i].index = 0; + switch(Index) + { + case TILE_DEATH: + m_pTiles[i].m_Index = COLFLAG_DEATH; + break; + case TILE_SOLID: + m_pTiles[i].m_Index = COLFLAG_SOLID; + break; + case TILE_NOHOOK: + m_pTiles[i].m_Index = COLFLAG_SOLID|COLFLAG_NOHOOK; + break; + default: + m_pTiles[i].m_Index = 0; + } } - - return 1; } - -int col_get(int x, int y) +int CCollision::GetTile(int x, int y) { - int nx = clamp(x/32, 0, width-1); - int ny = clamp(y/32, 0, height-1); + int nx = clamp(x/32, 0, m_Width-1); + int ny = clamp(y/32, 0, m_Height-1); - if(tiles[ny*width+nx].index > 128) - return 0; - return tiles[ny*width+nx].index; + return m_pTiles[ny*m_Width+nx].m_Index > 128 ? 0 : m_pTiles[ny*m_Width+nx].m_Index; } -int col_is_solid(int x, int y) +bool CCollision::IsTileSolid(int x, int y) { - return col_get(x,y)&COLFLAG_SOLID; + return GetTile(x,y)&COLFLAG_SOLID; } - // TODO: rewrite this smarter! -int col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision) +int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) { - float d = distance(pos0, pos1); - vec2 last = pos0; + float d = distance(Pos0, Pos1); + vec2 Last = Pos0; for(float f = 0; f < d; f++) { float a = f/d; - vec2 pos = mix(pos0, pos1, a); - if(col_is_solid(round(pos.x), round(pos.y))) + vec2 Pos = mix(Pos0, Pos1, a); + if(CheckPoint(Pos.x, Pos.y)) { - if(out_collision) - *out_collision = pos; - if(out_before_collision) - *out_before_collision = last; - return col_get(round(pos.x), round(pos.y)); + if(pOutCollision) + *pOutCollision = Pos; + if(pOutBeforeCollision) + *pOutBeforeCollision = Last; + return GetCollisionAt(Pos.x, Pos.y); } - last = pos; + Last = Pos; } - if(out_collision) - *out_collision = pos1; - if(out_before_collision) - *out_before_collision = pos1; + if(pOutCollision) + *pOutCollision = Pos1; + if(pOutBeforeCollision) + *pOutBeforeCollision = Pos1; return 0; } + +// TODO: OPT: rewrite this smarter! +void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces) +{ + if(pBounces) + *pBounces = 0; + + vec2 Pos = *pInoutPos; + vec2 Vel = *pInoutVel; + if(CheckPoint(Pos + Vel)) + { + int Affected = 0; + if(CheckPoint(Pos.x + Vel.x, Pos.y)) + { + pInoutVel->x *= -Elasticity; + if(pBounces) + (*pBounces)++; + Affected++; + } + + if(CheckPoint(Pos.x, Pos.y + Vel.y)) + { + pInoutVel->y *= -Elasticity; + if(pBounces) + (*pBounces)++; + Affected++; + } + + if(Affected == 0) + { + pInoutVel->x *= -Elasticity; + pInoutVel->y *= -Elasticity; + } + } + else + { + *pInoutPos = Pos + Vel; + } +} + +bool CCollision::TestBox(vec2 Pos, vec2 Size) +{ + Size *= 0.5f; + if(CheckPoint(Pos.x-Size.x, Pos.y-Size.y)) + return true; + if(CheckPoint(Pos.x+Size.x, Pos.y-Size.y)) + return true; + if(CheckPoint(Pos.x-Size.x, Pos.y+Size.y)) + return true; + if(CheckPoint(Pos.x+Size.x, Pos.y+Size.y)) + return true; + return false; +} + +void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity) +{ + // do the move + vec2 Pos = *pInoutPos; + vec2 Vel = *pInoutVel; + + float Distance = length(Vel); + int Max = (int)Distance; + + if(Distance > 0.00001f) + { + //vec2 old_pos = pos; + float Fraction = 1.0f/(float)(Max+1); + for(int i = 0; i <= Max; i++) + { + //float amount = i/(float)max; + //if(max == 0) + //amount = 0; + + vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice + + if(TestBox(vec2(NewPos.x, NewPos.y), Size)) + { + int Hits = 0; + + if(TestBox(vec2(Pos.x, NewPos.y), Size)) + { + NewPos.y = Pos.y; + Vel.y *= -Elasticity; + Hits++; + } + + if(TestBox(vec2(NewPos.x, Pos.y), Size)) + { + NewPos.x = Pos.x; + Vel.x *= -Elasticity; + Hits++; + } + + // neither of the tests got a collision. + // this is a real _corner case_! + if(Hits == 0) + { + NewPos.y = Pos.y; + Vel.y *= -Elasticity; + NewPos.x = Pos.x; + Vel.x *= -Elasticity; + } + } + + Pos = NewPos; + } + } + + *pInoutPos = Pos; + *pInoutVel = Vel; +} diff --git a/src/game/collision.h b/src/game/collision.h new file mode 100644 index 00000000..66603890 --- /dev/null +++ b/src/game/collision.h @@ -0,0 +1,37 @@ +#ifndef GAME_COLLISION_H +#define GAME_COLLISION_H + +#include <base/vmath.h> + +class CCollision +{ + class CTile *m_pTiles; + int m_Width; + int m_Height; + class CLayers *m_pLayers; + + bool IsTileSolid(int x, int y); + int GetTile(int x, int y); + +public: + enum + { + COLFLAG_SOLID=1, + COLFLAG_DEATH=2, + COLFLAG_NOHOOK=4, + }; + + CCollision(); + void Init(class CLayers *pLayers); + bool CheckPoint(float x, float y) { return IsTileSolid(round(x), round(y)); } + bool CheckPoint(vec2 p) { return CheckPoint(p.x, p.y); } + int GetCollisionAt(float x, float y) { return GetTile(round(x), round(y)); } + int GetWidth() { return m_Width; }; + int GetHeight() { return m_Height; }; + int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision); + void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *Bpounces); + void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity); + bool TestBox(vec2 Pos, vec2 Size); +}; + +#endif diff --git a/src/game/collision.hpp b/src/game/collision.hpp deleted file mode 100644 index 0f072daa..00000000 --- a/src/game/collision.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#ifndef GAME_MAPRES_COL_H -#define GAME_MAPRES_COL_H - -#include <base/vmath.hpp> - -enum -{ - COLFLAG_SOLID=1, - COLFLAG_DEATH=2, - COLFLAG_NOHOOK=4, -}; - -int col_init(); -int col_is_solid(int x, int y); -int col_get(int x, int y); -int col_width(); -int col_height(); -int col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision); - -#endif diff --git a/src/game/editor/array.hpp b/src/game/editor/array.hpp deleted file mode 100755 index fe9f2739..00000000 --- a/src/game/editor/array.hpp +++ /dev/null @@ -1,238 +0,0 @@ - -template <class T> -class array -{ - // - // - void init() - { - list = 0; - clear(); - } - -public: - array() - { - init(); - } - - // - array(const array &other) - { - init(); - setsize(other.len()); - for(int i = 0; i < len(); i++) - (*this)[i] = other[i]; - } - - - // - // - virtual ~array() - { - delete [] list; - list = 0; - } - - // - // - void deleteall() - { - for(int i = 0; i < len(); i++) - delete list[i]; - - clear(); - } - - - // - // - void clear() - { - delete [] list; - - list_size = 1; - list = new T[1]; - num_elements = 0; - } - - int find(T val) - { - for(int i = 0; i < len(); i++) - if((*this)[i] == val) - return i; - return -1; - } - - bool exist(T val) - { - return find(val) != -1; - } - - // - // returns the number of elements in the list - // - int len() const - { - return num_elements; - } - - // - // This doesn't conserve the order in the list. Be careful - // - void removebyindexfast(int index) - { - //ASSUME(_Pos >= 0 && _Pos < num_elements); - list[index] = list[num_elements-1]; - setsize(len()-1); - } - - void removefast(const T& _Elem) - { - for(int i = 0; i < len(); i++) - if(list[i] == _Elem) - { - removebyindexfast(i); - return; - } - } - - // - // - void removebyindex(int index) - { - //ASSUME(_Pos >= 0 && _Pos < num_elements); - - for(int i = index+1; i < num_elements; i++) - list[i-1] = list[i]; - - setsize(len()-1); - } - - void insert(int index, const T& element) - { - int some_len = len(); - if (index < some_len) - setsize(some_len+1); - else - setsize(index + 1); - - for(int i = num_elements-2; i >= index; i--) - list[i+1] = list[i]; - - list[index] = element; - } - - bool remove(const T& element) - { - for(int i = 0; i < len(); i++) - if(list[i] == element) - { - removebyindex(i); - return true; - } - return false; - } - - // - // - int add(const T& element) - { - //if(num_elements == list_size) - setsize(len()+1); - list[num_elements-1] = element; - return num_elements-1; - } - - // - // - int add(const T& elem, int index) - { - setsize(len()+1); - - for(int i = num_elements-1; i > index; i--) - list[i] = list[i-1]; - - list[index] = elem; - - //num_elements++; - return num_elements-1; - } - - // - // - T& operator[] (int index) - { - return list[index]; - } - - const T& operator[] (int index) const - { - return list[index]; - } - - // - // - T *getptr() - { - return list; - } - - const T *getptr() const - { - return list; - } - - // - // - // - void setsize(int new_len) - { - if (list_size < new_len) - allocsize(new_len); - num_elements = new_len; - } - - // removes unnessasary data, returns how many bytes was earned - int optimize() - { - int Before = memoryusage(); - setsize(num_elements); - return Before - memoryusage(); - } - - // returns how much memory this dynamic array is using - int memoryusage() - { - return sizeof(array) + sizeof(T)*list_size; - } - - // - array &operator = (const array &other) - { - setsize(other.len()); - for(int i = 0; i < len(); i++) - (*this)[i] = other[i]; - return *this; - } -private: - void allocsize(int new_len) - { - list_size = new_len; - T *new_list = new T[list_size]; - - long end = num_elements < list_size ? num_elements : list_size; - for(int i = 0; i < end; i++) - new_list[i] = list[i]; - - delete [] list; - list = 0; - num_elements = num_elements < list_size ? num_elements : list_size; - list = new_list; - } - - T *list; - long list_size; - long num_elements; -}; - diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp index 17b891fc..480a6827 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/ed_editor.cpp @@ -1,185 +1,180 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info #include <base/system.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <engine/e_common_interface.h> -#include <engine/e_datafile.h> -#include <engine/e_config.h> -#include <engine/e_engine.h> -#include <engine/client/graphics.h> +#include <engine/shared/datafile.h> +#include <engine/shared/config.h> +#include <engine/shared/engine.h> +#include <engine/client.h> +#include <engine/graphics.h> +#include <engine/textrender.h> +#include <engine/input.h> +#include <engine/keys.h> +#include <engine/storage.h> -#include <game/client/ui.hpp> -#include <game/gamecore.hpp> -#include <game/client/render.hpp> +#include <game/client/ui.h> +#include <game/gamecore.h> +#include <game/client/render.h> -#include "ed_editor.hpp" -#include <game/client/lineinput.hpp> +#include "ed_editor.h" +#include <game/client/lineinput.h> -static int checker_texture = 0; -static int background_texture = 0; -static int cursor_texture = 0; -static int entities_texture = 0; +int CEditor::ms_CheckerTexture; +int CEditor::ms_BackgroundTexture; +int CEditor::ms_CursorTexture; +int CEditor::ms_EntitiesTexture; +const void* CEditor::ms_pUiGotContext; enum { BUTTON_CONTEXT=1, }; - - -EDITOR_IMAGE::~EDITOR_IMAGE() +CEditorImage::~CEditorImage() { - editor->Graphics()->UnloadTexture(tex_id); + m_pEditor->Graphics()->UnloadTexture(m_TexId); } -static const void *ui_got_context = 0; - -LAYERGROUP::LAYERGROUP() +CLayerGroup::CLayerGroup() { - name = ""; - visible = true; - game_group = false; - offset_x = 0; - offset_y = 0; - parallax_x = 100; - parallax_y = 100; - - use_clipping = 0; - clip_x = 0; - clip_y = 0; - clip_w = 0; - clip_h = 0; + m_pName = ""; + m_Visible = true; + m_GameGroup = false; + m_OffsetX = 0; + m_OffsetY = 0; + m_ParallaxX = 100; + m_ParallaxY = 100; + + m_UseClipping = 0; + m_ClipX = 0; + m_ClipY = 0; + m_ClipW = 0; + m_ClipH = 0; } -LAYERGROUP::~LAYERGROUP() +CLayerGroup::~CLayerGroup() { - clear(); + Clear(); } -void LAYERGROUP::convert(CUIRect *rect) +void CLayerGroup::Convert(CUIRect *pRect) { - rect->x += offset_x; - rect->y += offset_y; + pRect->x += m_OffsetX; + pRect->y += m_OffsetY; } -void LAYERGROUP::mapping(float *points) +void CLayerGroup::Mapping(float *pPoints) { - m_pMap->editor->RenderTools()->mapscreen_to_world( - m_pMap->editor->world_offset_x, m_pMap->editor->world_offset_y, - parallax_x/100.0f, parallax_y/100.0f, - offset_x, offset_y, - m_pMap->editor->Graphics()->ScreenAspect(), m_pMap->editor->world_zoom, points); - - points[0] += m_pMap->editor->editor_offset_x; - points[1] += m_pMap->editor->editor_offset_y; - points[2] += m_pMap->editor->editor_offset_x; - points[3] += m_pMap->editor->editor_offset_y; + m_pMap->m_pEditor->RenderTools()->MapscreenToWorld( + m_pMap->m_pEditor->m_WorldOffsetX, m_pMap->m_pEditor->m_WorldOffsetY, + m_ParallaxX/100.0f, m_ParallaxY/100.0f, + m_OffsetX, m_OffsetY, + m_pMap->m_pEditor->Graphics()->ScreenAspect(), m_pMap->m_pEditor->m_WorldZoom, pPoints); + + pPoints[0] += m_pMap->m_pEditor->m_EditorOffsetX; + pPoints[1] += m_pMap->m_pEditor->m_EditorOffsetY; + pPoints[2] += m_pMap->m_pEditor->m_EditorOffsetX; + pPoints[3] += m_pMap->m_pEditor->m_EditorOffsetY; } -void LAYERGROUP::mapscreen() +void CLayerGroup::MapScreen() { - float points[4]; - mapping(points); - m_pMap->editor->Graphics()->MapScreen(points[0], points[1], points[2], points[3]); + float aPoints[4]; + Mapping(aPoints); + m_pMap->m_pEditor->Graphics()->MapScreen(aPoints[0], aPoints[1], aPoints[2], aPoints[3]); } -void LAYERGROUP::render() +void CLayerGroup::Render() { - mapscreen(); - IGraphics *pGraphics = m_pMap->editor->Graphics(); - - if(use_clipping) - { - float points[4]; - m_pMap->game_group->mapping(points); - float x0 = (clip_x - points[0]) / (points[2]-points[0]); - float y0 = (clip_y - points[1]) / (points[3]-points[1]); - float x1 = ((clip_x+clip_w) - points[0]) / (points[2]-points[0]); - float y1 = ((clip_y+clip_h) - points[1]) / (points[3]-points[1]); - + MapScreen(); + IGraphics *pGraphics = m_pMap->m_pEditor->Graphics(); + + if(m_UseClipping) + { + float aPoints[4]; + m_pMap->m_pGameGroup->Mapping(aPoints); + float x0 = (m_ClipX - aPoints[0]) / (aPoints[2]-aPoints[0]); + float y0 = (m_ClipY - aPoints[1]) / (aPoints[3]-aPoints[1]); + float x1 = ((m_ClipX+m_ClipW) - aPoints[0]) / (aPoints[2]-aPoints[0]); + float y1 = ((m_ClipY+m_ClipH) - aPoints[1]) / (aPoints[3]-aPoints[1]); + pGraphics->ClipEnable((int)(x0*pGraphics->ScreenWidth()), (int)(y0*pGraphics->ScreenHeight()), (int)((x1-x0)*pGraphics->ScreenWidth()), (int)((y1-y0)*pGraphics->ScreenHeight())); } - - for(int i = 0; i < layers.len(); i++) + + for(int i = 0; i < m_lLayers.size(); i++) { - if(layers[i]->visible && layers[i] != m_pMap->game_layer) + if(m_lLayers[i]->m_Visible && m_lLayers[i] != m_pMap->m_pGameLayer) { - if(m_pMap->editor->show_detail || !(layers[i]->flags&LAYERFLAG_DETAIL)) - layers[i]->render(); + if(m_pMap->m_pEditor->m_ShowDetail || !(m_lLayers[i]->m_Flags&LAYERFLAG_DETAIL)) + m_lLayers[i]->Render(); } } - + pGraphics->ClipDisable(); } -bool LAYERGROUP::is_empty() const { return layers.len() == 0; } -void LAYERGROUP::clear() { layers.deleteall(); } -void LAYERGROUP::add_layer(LAYER *l) { layers.add(l); } - -void LAYERGROUP::delete_layer(int index) +void CLayerGroup::DeleteLayer(int Index) { - if(index < 0 || index >= layers.len()) return; - delete layers[index]; - layers.removebyindex(index); -} + if(Index < 0 || Index >= m_lLayers.size()) return; + delete m_lLayers[Index]; + m_lLayers.remove_index(Index); +} -void LAYERGROUP::get_size(float *w, float *h) +void CLayerGroup::GetSize(float *w, float *h) { *w = 0; *h = 0; - for(int i = 0; i < layers.len(); i++) + for(int i = 0; i < m_lLayers.size(); i++) { float lw, lh; - layers[i]->get_size(&lw, &lh); + m_lLayers[i]->GetSize(&lw, &lh); *w = max(*w, lw); *h = max(*h, lh); } } -int LAYERGROUP::swap_layers(int index0, int index1) +int CLayerGroup::SwapLayers(int Index0, int Index1) { - if(index0 < 0 || index0 >= layers.len()) return index0; - if(index1 < 0 || index1 >= layers.len()) return index0; - if(index0 == index1) return index0; - swap(layers[index0], layers[index1]); - return index1; + if(Index0 < 0 || Index0 >= m_lLayers.size()) return Index0; + if(Index1 < 0 || Index1 >= m_lLayers.size()) return Index0; + if(Index0 == Index1) return Index0; + swap(m_lLayers[Index0], m_lLayers[Index1]); + return Index1; } -void EDITOR_IMAGE::analyse_tileflags() +void CEditorImage::AnalyseTileFlags() { - mem_zero(tileflags, sizeof(tileflags)); - - int tw = width/16; // tilesizes - int th = height/16; - if ( tw == th ) { - unsigned char *pixeldata = (unsigned char *)data; - - int tile_id = 0; + mem_zero(m_aTileFlags, sizeof(m_aTileFlags)); + + int tw = m_Width/16; // tilesizes + int th = m_Height/16; + if ( tw == th ) + { + unsigned char *pPixelData = (unsigned char *)m_pData; + + int TileId = 0; for(int ty = 0; ty < 16; ty++) - for(int tx = 0; tx < 16; tx++, tile_id++) + for(int tx = 0; tx < 16; tx++, TileId++) { - bool opaque = true; + bool Opaque = true; for(int x = 0; x < tw; x++) for(int y = 0; y < th; y++) { - int p = (ty*tw+y)*width + tx*tw+x; - if(pixeldata[p*4+3] < 250) + int p = (ty*tw+y)*m_Width + tx*tw+x; + if(pPixelData[p*4+3] < 250) { - opaque = false; + Opaque = false; break; } } - - if(opaque) - tileflags[tile_id] |= TILEFLAG_OPAQUE; + + if(Opaque) + m_aTileFlags[TileId] |= TILEFLAG_OPAQUE; } } - + } /******************************************************** @@ -189,42 +184,42 @@ void EDITOR_IMAGE::analyse_tileflags() // copied from gc_menu.cpp, should be more generalized //extern int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false); -int EDITOR::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden) +int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden) { int Inside = UI()->MouseInside(pRect); int ReturnValue = 0; - static int AtIndex = 0; + static int s_AtIndex = 0; if(UI()->LastActiveItem() == pID) { - int Len = strlen(pStr); - + int Len = str_length(pStr); + if(Inside && UI()->MouseButton(0)) { - int mx_rel = (int)(UI()->MouseX() - pRect->x); + int MxRel = (int)(UI()->MouseX() - pRect->x); for (int i = 1; i <= Len; i++) { - if (gfx_text_width(0, FontSize, pStr, i) + 10 > mx_rel) + if (TextRender()->TextWidth(0, FontSize, pStr, i) + 10 > MxRel) { - AtIndex = i - 1; + s_AtIndex = i - 1; break; } if (i == Len) - AtIndex = Len; + s_AtIndex = Len; } } - for(int i = 0; i < inp_num_events(); i++) + for(int i = 0; i < Input()->NumEvents(); i++) { - Len = strlen(pStr); - LINEINPUT::manipulate(inp_get_event(i), pStr, StrSize, &Len, &AtIndex); + Len = str_length(pStr); + CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, &Len, &s_AtIndex); } } bool JustGotActive = false; - + if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) @@ -239,219 +234,138 @@ int EDITOR::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS UI()->SetActiveItem(pID); } } - + if(Inside) UI()->SetHotItem(pID); CUIRect Textbox = *pRect; - RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); - Textbox.VMargin(5.0f, &Textbox); - + RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 3.0f); + Textbox.VMargin(3.0f, &Textbox); + const char *pDisplayStr = pStr; char aStars[128]; - + if(Hidden) { - unsigned s = strlen(pStr); + unsigned s = str_length(pStr); if(s >= sizeof(aStars)) s = sizeof(aStars)-1; - memset(aStars, '*', s); + for(unsigned int i = 0; i < s; ++i) + aStars[i] = '*'; aStars[s] = 0; pDisplayStr = aStars; } UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1); - if (UI()->LastActiveItem() == pID && !JustGotActive) + //TODO: make it blink + if(UI()->LastActiveItem() == pID && !JustGotActive) { - float w = gfx_text_width(0, FontSize, pDisplayStr, AtIndex); + float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); + Textbox = *pRect; + Textbox.VSplitLeft(2.0f, 0, &Textbox); Textbox.x += w*UI()->Scale(); - UI()->DoLabel(&Textbox, "_", FontSize, -1); - } - - return ReturnValue; -} - -/* -int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false) -{ - int inside = UI()->MouseInside(rect); - int r = 0; - static int at_index = 0; - - if(UI()->LastActiveItem() == id) - { - int len = strlen(str); - - if (inside && UI()->MouseButton(0)) - { - int mx_rel = (int)(UI()->MouseX() - rect->x); - - for (int i = 1; i <= len; i++) - { - if (gfx_text_width(0, font_size, str, i) + 10 > mx_rel) - { - at_index = i - 1; - break; - } - - if (i == len) - at_index = len; - } - } - - for(int i = 0; i < inp_num_events(); i++) - { - len = strlen(str); - LINEINPUT::manipulate(inp_get_event(i), str, str_size, &len, &at_index); - } + Textbox.y -= FontSize/10.f; - r = 1; - } - - bool just_got_active = false; - - if(UI()->ActiveItem() == id) - { - if(!UI()->MouseButton(0)) - UI()->SetActiveItem(0); - } - else if(UI()->HotItem() == id) - { - if(UI()->MouseButton(0)) - { - if (UI()->LastActiveItem() != id) - just_got_active = true; - UI()->SetActiveItem(id); - } - } - - if(inside) - UI()->SetHotItem(id); - - CUIRect textbox = *rect; - RenderTools()->DrawUIRect(&textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); - textbox.VMargin(5.0f, &textbox); - - const char *display_str = str; - char stars[128]; - - if(hidden) - { - unsigned s = strlen(str); - if(s >= sizeof(stars)) - s = sizeof(stars)-1; - memset(stars, '*', s); - stars[s] = 0; - display_str = stars; - } - - UI()->DoLabel(&textbox, display_str, font_size, -1); - - if (UI()->LastActiveItem() == id && !just_got_active) - { - float w = gfx_text_width(0, font_size, display_str, at_index); - textbox.x += w*UI()->Scale(); - UI()->DoLabel(&textbox, "_", font_size, -1); + UI()->DoLabel(&Textbox, "|", FontSize*1.1f, -1); } - return r; + return ReturnValue; } -*/ -vec4 EDITOR::button_color_mul(const void *id) +vec4 CEditor::ButtonColorMul(const void *pId) { - if(UI()->ActiveItem() == id) + if(UI()->ActiveItem() == pId) return vec4(1,1,1,0.5f); - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) return vec4(1,1,1,1.5f); return vec4(1,1,1,1); } -float EDITOR::ui_do_scrollbar_v(const void *id, const CUIRect *rect, float current) +float CEditor::UiDoScrollbarV(const void *pId, const CUIRect *pRect, float Current) { - CUIRect handle; - static float offset_y; - rect->HSplitTop(33, &handle, 0); + CUIRect Handle; + static float s_OffsetY; + pRect->HSplitTop(33, &Handle, 0); - handle.y += (rect->h-handle.h)*current; + Handle.y += (pRect->h-Handle.h)*Current; - /* logic */ - float ret = current; - int inside = UI()->MouseInside(&handle); + // logic + float Ret = Current; + int Inside = UI()->MouseInside(&Handle); - if(UI()->ActiveItem() == id) + if(UI()->ActiveItem() == pId) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - - float min = rect->y; - float max = rect->h-handle.h; - float cur = UI()->MouseY()-offset_y; - ret = (cur-min)/max; - if(ret < 0.0f) ret = 0.0f; - if(ret > 1.0f) ret = 1.0f; + + float Min = pRect->y; + float Max = pRect->h-Handle.h; + float Cur = UI()->MouseY()-s_OffsetY; + Ret = (Cur-Min)/Max; + if(Ret < 0.0f) Ret = 0.0f; + if(Ret > 1.0f) Ret = 1.0f; } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) { if(UI()->MouseButton(0)) { - UI()->SetActiveItem(id); - offset_y = UI()->MouseY()-handle.y; + UI()->SetActiveItem(pId); + s_OffsetY = UI()->MouseY()-Handle.y; } } - - if(inside) - UI()->SetHotItem(id); + + if(Inside) + UI()->SetHotItem(pId); // render - CUIRect rail; - rect->VMargin(5.0f, &rail); - RenderTools()->DrawUIRect(&rail, vec4(1,1,1,0.25f), 0, 0.0f); - - CUIRect slider = handle; - slider.w = rail.x-slider.x; - RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f), CUI::CORNER_L, 2.5f); - slider.x = rail.x+rail.w; - RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f), CUI::CORNER_R, 2.5f); - - slider = handle; - slider.Margin(5.0f, &slider); - RenderTools()->DrawUIRect(&slider, vec4(1,1,1,0.25f)*button_color_mul(id), CUI::CORNER_ALL, 2.5f); - - return ret; + CUIRect Rail; + pRect->VMargin(5.0f, &Rail); + RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.0f); + + CUIRect Slider = Handle; + Slider.w = Rail.x-Slider.x; + RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_L, 2.5f); + Slider.x = Rail.x+Rail.w; + RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_R, 2.5f); + + Slider = Handle; + Slider.Margin(5.0f, &Slider); + RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pId), CUI::CORNER_ALL, 2.5f); + + return Ret; } -vec4 EDITOR::get_button_color(const void *id, int checked) +vec4 CEditor::GetButtonColor(const void *pId, int Checked) { - if(checked < 0) + if(Checked < 0) return vec4(0,0,0,0.5f); - - if(checked > 0) + + if(Checked > 0) { - if(UI()->HotItem() == id) + if(UI()->HotItem() == pId) return vec4(1,0,0,0.75f); return vec4(1,0,0,0.5f); } - - if(UI()->HotItem() == id) + + if(UI()->HotItem() == pId) return vec4(1,1,1,0.75f); return vec4(1,1,1,0.5f); } -int EDITOR::DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { if(UI()->MouseInside(pRect)) { if(Flags&BUTTON_CONTEXT) - ui_got_context = pID; - if(tooltip) - tooltip = pToolTip; + ms_pUiGotContext = pID; + if(m_pTooltip) + m_pTooltip = pToolTip; } - + if(UI()->HotItem() == pID && pToolTip) - tooltip = (const char *)pToolTip; - + m_pTooltip = (const char *)pToolTip; + return UI()->DoButtonLogic(pID, pText, Checked, pRect); // Draw here @@ -459,444 +373,399 @@ int EDITOR::DoButton_Editor_Common(const void *pID, const char *pText, int Check } -int EDITOR::DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f); - UI()->DoLabel(pRect, pText, 10, 0, -1); + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f); + CUIRect NewRect = *pRect; + NewRect.y += NewRect.h/2.0f-7.0f; + UI()->DoLabel(&NewRect, pText, 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -int EDITOR::DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { if(UI()->HotItem() == pID) - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f); - + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f); + CUIRect t = *pRect; t.VMargin(5.0f, &t); UI()->DoLabel(&t, pText, 10, -1, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -//static void draw_editor_button_menu(const void *id, const char *text, int checked, const CUIRect *rect, const void *extra) -int EDITOR::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { - /* - if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra; - if(UI()->HotItem() == id) - RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_ALL, 3.0f); - */ - CUIRect r = *pRect; - /* - if(ui_popups[id == id) - { - RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), CUI::CORNER_T, 3.0f); - r.Margin(1.0f, &r); - RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), CUI::CORNER_T, 3.0f); - } - else*/ - RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f, 1.0f), CUI::CORNER_T, 3.0f); - + RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f); r = *pRect; r.VMargin(5.0f, &r); UI()->DoLabel(&r, pText, 10, -1, -1); - return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); - - //CUIRect t = *r; } -int EDITOR::DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { if(UI()->HotItem() == pID || Checked) - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_ALL, 3.0f); - + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_ALL, 3.0f); + CUIRect t = *pRect; t.VMargin(5.0f, &t); UI()->DoLabel(&t, pText, 10, -1, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, 0, 0); } -int EDITOR::DoButton_ButtonL(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) -{ - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_L, 3.0f); - UI()->DoLabel(pRect, pText, 10, 0, -1); - return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); -} - -int EDITOR::DoButton_ButtonM(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), 0, 3.0f); - UI()->DoLabel(pRect, pText, 10, 0, -1); + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_T, 5.0f); + CUIRect NewRect = *pRect; + NewRect.y += NewRect.h/2.0f-7.0f; + UI()->DoLabel(&NewRect, pText, 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -int EDITOR::DoButton_ButtonR(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners) { - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_R, 3.0f); - UI()->DoLabel(pRect, pText, 10, 0, -1); + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), Corners, 3.0f); + CUIRect NewRect = *pRect; + NewRect.y += NewRect.h/2.0f-7.0f; + UI()->DoLabel(&NewRect, pText, 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -int EDITOR::DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_R, 3.0f); - UI()->DoLabel(pRect, pText?pText:">", 10, 0, -1); + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_R, 3.0f); + UI()->DoLabel(pRect, pText?pText:"+", 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -int EDITOR::DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) +int CEditor::DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { - RenderTools()->DrawUIRect(pRect, get_button_color(pID, Checked), CUI::CORNER_L, 3.0f); - UI()->DoLabel(pRect, pText?pText:"<", 10, 0, -1); + RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_L, 3.0f); + UI()->DoLabel(pRect, pText?pText:"-", 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -/* -static void draw_editor_button_l(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) -{ - RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_L, 3.0f); - UI()->DoLabel(r, text, 10, 0, -1); -} - -static void draw_editor_button_m(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) -{ - if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra; - RenderTools()->DrawUIRect(r, get_button_color(id, checked), 0, 3.0f); - UI()->DoLabel(r, text, 10, 0, -1); -} - -static void draw_editor_button_r(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) -{ - if(UI()->HotItem() == id) if(extra) editor.tooltip = (const char *)extra; - RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_R, 3.0f); - UI()->DoLabel(r, text, 10, 0, -1); -} - -static void draw_inc_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) +void CEditor::RenderBackground(CUIRect View, int Texture, float Size, float Brightness) { - if(UI()->HotItem == id) if(extra) editor.tooltip = (const char *)extra; - RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_R, 3.0f); - UI()->DoLabel(r, text?text:">", 10, 0, -1); -} - -static void draw_dec_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra) -{ - if(UI()->HotItem == id) if(extra) editor.tooltip = (const char *)extra; - RenderTools()->DrawUIRect(r, get_button_color(id, checked), CUI::CORNER_L, 3.0f); - UI()->DoLabel(r, text?text:"<", 10, 0, -1); -} - -int do_editor_button(const void *id, const char *text, int checked, const CUIRect *r, ui_draw_button_func draw_func, int flags, const char *tooltip) -{ - if(UI()->MouseInside(r)) - { - if(flags&BUTTON_CONTEXT) - ui_got_context = id; - if(tooltip) - editor.tooltip = tooltip; - } - - return UI()->DoButton(id, text, checked, r, draw_func, 0); -}*/ - - -void EDITOR::render_background(CUIRect view, int texture, float size, float brightness) -{ - Graphics()->TextureSet(texture); + Graphics()->TextureSet(Texture); Graphics()->BlendNormal(); Graphics()->QuadsBegin(); - Graphics()->SetColor(brightness,brightness,brightness,1.0f); - Graphics()->QuadsSetSubset(0,0, view.w/size, view.h/size); - Graphics()->QuadsDrawTL(view.x, view.y, view.w, view.h); + Graphics()->SetColor(Brightness, Brightness, Brightness, 1.0f); + Graphics()->QuadsSetSubset(0,0, View.w/Size, View.h/Size); + IGraphics::CQuadItem QuadItem(View.x, View.y, View.w, View.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } -static LAYERGROUP brush; -static LAYER_TILES tileset_picker(16, 16); - -int EDITOR::ui_do_value_selector(void *id, CUIRect *r, const char *label, int current, int min, int max, float scale) +int CEditor::UiDoValueSelector(void *pId, CUIRect *r, const char *pLabel, int Current, int Min, int Max, float Scale) { - /* logic */ - static float value; - int ret = 0; - int inside = UI()->MouseInside(r); + // logic + static float s_Value; + int Ret = 0; + int Inside = UI()->MouseInside(r); - if(UI()->ActiveItem() == id) + if(UI()->ActiveItem() == pId) { if(!UI()->MouseButton(0)) { - if(inside) - ret = 1; - lock_mouse = false; + if(Inside) + Ret = 1; + m_LockMouse = false; UI()->SetActiveItem(0); } else { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - value += mouse_delta_x*0.05f; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + s_Value += m_MouseDeltaX*0.05f; else - value += mouse_delta_x; - - if(fabs(value) > scale) + s_Value += m_MouseDeltaX; + + if(absolute(s_Value) > Scale) { - int count = (int)(value/scale); - value = fmod(value, scale); - current += count; - if(current < min) - current = min; - if(current > max) - current = max; + int Count = (int)(s_Value/Scale); + s_Value = fmod(s_Value, Scale); + Current += Count; + if(Current < Min) + Current = Min; + if(Current > Max) + Current = Max; } } } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) { if(UI()->MouseButton(0)) { - lock_mouse = true; - value = 0; - UI()->SetActiveItem(id); + m_LockMouse = true; + s_Value = 0; + UI()->SetActiveItem(pId); } } - - if(inside) - UI()->SetHotItem(id); + + if(Inside) + UI()->SetHotItem(pId); // render - char buf[128]; - sprintf(buf, "%s %d", label, current); - RenderTools()->DrawUIRect(r, get_button_color(id, 0), CUI::CORNER_ALL, 5.0f); - UI()->DoLabel(r, buf, 10, 0, -1); - return current; + char aBuf[128]; + str_format(aBuf, sizeof(aBuf),"%s %d", pLabel, Current); + RenderTools()->DrawUIRect(r, GetButtonColor(pId, 0), CUI::CORNER_ALL, 5.0f); + r->y += r->h/2.0f-7.0f; + UI()->DoLabel(r, aBuf, 10, 0, -1); + + return Current; } -LAYERGROUP *EDITOR::get_selected_group() +CLayerGroup *CEditor::GetSelectedGroup() { - if(selected_group >= 0 && selected_group < map.groups.len()) - return map.groups[selected_group]; + if(m_SelectedGroup >= 0 && m_SelectedGroup < m_Map.m_lGroups.size()) + return m_Map.m_lGroups[m_SelectedGroup]; return 0x0; } -LAYER *EDITOR::get_selected_layer(int index) +CLayer *CEditor::GetSelectedLayer(int Index) { - LAYERGROUP *group = get_selected_group(); - if(!group) + CLayerGroup *pGroup = GetSelectedGroup(); + if(!pGroup) return 0x0; - if(selected_layer >= 0 && selected_layer < map.groups[selected_group]->layers.len()) - return group->layers[selected_layer]; + if(m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size()) + return pGroup->m_lLayers[m_SelectedLayer]; return 0x0; } -LAYER *EDITOR::get_selected_layer_type(int index, int type) +CLayer *CEditor::GetSelectedLayerType(int Index, int Type) { - LAYER *p = get_selected_layer(index); - if(p && p->type == type) + CLayer *p = GetSelectedLayer(Index); + if(p && p->m_Type == Type) return p; return 0x0; } -QUAD *EDITOR::get_selected_quad() +CQuad *CEditor::GetSelectedQuad() { - LAYER_QUADS *ql = (LAYER_QUADS *)get_selected_layer_type(0, LAYERTYPE_QUADS); + CLayerQuads *ql = (CLayerQuads *)GetSelectedLayerType(0, LAYERTYPE_QUADS); if(!ql) return 0; - if(selected_quad >= 0 && selected_quad < ql->quads.len()) - return &ql->quads[selected_quad]; + if(m_SelectedQuad >= 0 && m_SelectedQuad < ql->m_lQuads.size()) + return &ql->m_lQuads[m_SelectedQuad]; return 0; } -static void callback_open_map(const char *filename, void *user) { ((EDITOR*)user)->load(filename); } -static void callback_append_map(const char *filename, void *user) { ((EDITOR*)user)->append(filename); } -static void callback_save_map(const char *filename, void *user) { ((EDITOR*)user)->save(filename); } +static void CallbackOpenMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Load(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); } +static void CallbackAppendMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Append(pFileName)) ((CEditor*)pUser)->m_aFileName[0] = 0; } +static void CallbackSaveMap(const char *pFileName, void *pUser){ if(((CEditor*)pUser)->Save(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); } -void EDITOR::do_toolbar(CUIRect toolbar) +void CEditor::DoToolbar(CUIRect ToolBar) { - CUIRect button; + CUIRect TB_Top, TB_Bottom; + CUIRect Button; - // ctrl+o to open - if(inp_key_down('o') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))) - invoke_file_dialog(LISTDIRTYPE_ALL, "Open Map", "Open", "maps/", "", callback_open_map, this); + ToolBar.HSplitTop(ToolBar.h/2.0f, &TB_Top, &TB_Bottom); + TB_Top.HSplitBottom(2.5f, &TB_Top, 0); + TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom); + + // ctrl+o to open + if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) + InvokeFileDialog(IStorage::TYPE_ALL, "Open Map", "Open", "maps/", "", CallbackOpenMap, this); + // ctrl+s to save - if(inp_key_down('s') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))) - invoke_file_dialog(LISTDIRTYPE_SAVE, "Save Map", "Save", "maps/", "", callback_save_map, this); + if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) + { + if(m_aFileName[0]) + Save(m_aFileName); + else + InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, this); + } // detail button - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int hq_button = 0; - if(DoButton_Editor(&hq_button, "Detail", show_detail, &button, 0, "[ctrl+h] Toggle High Detail") || - (inp_key_down('h') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))) + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_HqButton = 0; + if(DoButton_Editor(&s_HqButton, "HD", m_ShowDetail, &Button, 0, "[ctrl+h] Toggle High Detail") || + (Input()->KeyDown('h') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))) { - show_detail = !show_detail; + m_ShowDetail = !m_ShowDetail; } - toolbar.VSplitLeft(5.0f, 0, &toolbar); - + TB_Top.VSplitLeft(5.0f, 0, &TB_Top); + // animation button - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int animate_button = 0; - if(DoButton_Editor(&animate_button, "Anim", animate, &button, 0, "[ctrl+m] Toggle animation") || - (inp_key_down('m') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))) + TB_Top.VSplitLeft(40.0f, &Button, &TB_Top); + static int s_AnimateButton = 0; + if(DoButton_Editor(&s_AnimateButton, "Anim", m_Animate, &Button, 0, "[ctrl+m] Toggle animation") || + (Input()->KeyDown('m') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))) { - animate_start = time_get(); - animate = !animate; + m_AnimateStart = time_get(); + m_Animate = !m_Animate; } - toolbar.VSplitLeft(5.0f, 0, &toolbar); + TB_Top.VSplitLeft(5.0f, 0, &TB_Top); // proof button - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int proof_button = 0; - if(DoButton_Editor(&proof_button, "Proof", proof_borders, &button, 0, "[ctrl-p] Toggles proof borders. These borders represent what a player maximum can see.") || - (inp_key_down('p') && (inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)))) + TB_Top.VSplitLeft(40.0f, &Button, &TB_Top); + static int s_ProofButton = 0; + if(DoButton_Editor(&s_ProofButton, "Proof", m_ProofBorders, &Button, 0, "[ctrl-p] Toggles proof borders. These borders represent what a player maximum can see.") || + (Input()->KeyDown('p') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))) { - proof_borders = !proof_borders; + m_ProofBorders = !m_ProofBorders; } - toolbar.VSplitLeft(15.0f, 0, &toolbar); - + TB_Top.VSplitLeft(15.0f, 0, &TB_Top); + // zoom group - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int zoom_out_button = 0; - if(DoButton_ButtonL(&zoom_out_button, "ZO", 0, &button, 0, "[NumPad-] Zoom out") || inp_key_down(KEY_KP_MINUS)) - zoom_level += 50; - - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int zoom_normal_button = 0; - if(DoButton_ButtonM(&zoom_normal_button, "1:1", 0, &button, 0, "[NumPad*] Zoom to normal and remove editor offset") || inp_key_down(KEY_KP_MULTIPLY)) + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_ZoomOutButton = 0; + if(DoButton_Ex(&s_ZoomOutButton, "ZO", 0, &Button, 0, "[NumPad-] Zoom out", CUI::CORNER_L) || Input()->KeyDown(KEY_KP_MINUS)) + m_ZoomLevel += 50; + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_ZoomNormalButton = 0; + if(DoButton_Ex(&s_ZoomNormalButton, "1:1", 0, &Button, 0, "[NumPad*] Zoom to normal and remove editor offset", 0) || Input()->KeyDown(KEY_KP_MULTIPLY)) { - editor_offset_x = 0; - editor_offset_y = 0; - zoom_level = 100; + m_EditorOffsetX = 0; + m_EditorOffsetY = 0; + m_ZoomLevel = 100; } - - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int zoom_in_button = 0; - if(DoButton_ButtonR(&zoom_in_button, "ZI", 0, &button, 0, "[NumPad+] Zoom in") || inp_key_down(KEY_KP_PLUS)) - zoom_level -= 50; - - toolbar.VSplitLeft(15.0f, 0, &toolbar); - + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_ZoomInButton = 0; + if(DoButton_Ex(&s_ZoomInButton, "ZI", 0, &Button, 0, "[NumPad+] Zoom in", CUI::CORNER_R) || Input()->KeyDown(KEY_KP_PLUS)) + m_ZoomLevel -= 50; + + TB_Top.VSplitLeft(10.0f, 0, &TB_Top); + // animation speed - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int anim_faster_button = 0; - if(DoButton_ButtonL(&anim_faster_button, "A+", 0, &button, 0, "Increase animation speed")) - animate_speed += 0.5f; - - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int anim_normal_button = 0; - if(DoButton_ButtonM(&anim_normal_button, "1", 0, &button, 0, "Normal animation speed")) - animate_speed = 1.0f; - - toolbar.VSplitLeft(16.0f, &button, &toolbar); - static int anim_slower_button = 0; - if(DoButton_ButtonR(&anim_slower_button, "A-", 0, &button, 0, "Decrease animation speed")) + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_AnimFasterButton = 0; + if(DoButton_Ex(&s_AnimFasterButton, "A+", 0, &Button, 0, "Increase animation speed", CUI::CORNER_L)) + m_AnimateSpeed += 0.5f; + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_AnimNormalButton = 0; + if(DoButton_Ex(&s_AnimNormalButton, "1", 0, &Button, 0, "Normal animation speed", 0)) + m_AnimateSpeed = 1.0f; + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_AnimSlowerButton = 0; + if(DoButton_Ex(&s_AnimSlowerButton, "A-", 0, &Button, 0, "Decrease animation speed", CUI::CORNER_R)) { - if(animate_speed > 0.5f) - animate_speed -= 0.5f; + if(m_AnimateSpeed > 0.5f) + m_AnimateSpeed -= 0.5f; } - - if(inp_key_presses(KEY_MOUSE_WHEEL_UP) && dialog == DIALOG_NONE) - zoom_level -= 20; - - if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN) && dialog == DIALOG_NONE) - zoom_level += 20; - - if(zoom_level < 50) - zoom_level = 50; - world_zoom = zoom_level/100.0f; - toolbar.VSplitLeft(10.0f, &button, &toolbar); + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && m_Dialog == DIALOG_NONE) + m_ZoomLevel -= 20; + + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && m_Dialog == DIALOG_NONE) + m_ZoomLevel += 20; + + if(m_ZoomLevel < 50) + m_ZoomLevel = 50; + m_WorldZoom = m_ZoomLevel/100.0f; + + TB_Top.VSplitLeft(10.0f, &Button, &TB_Top); // brush manipulation - { - int enabled = brush.is_empty()?-1:0; - + { + int Enabled = m_Brush.IsEmpty()?-1:0; + // flip buttons - toolbar.VSplitLeft(20.0f, &button, &toolbar); - static int flipx_button = 0; - if(DoButton_ButtonL(&flipx_button, "^X", enabled, &button, 0, "[N] Flip brush horizontal") || inp_key_down('n')) + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_FlipXButton = 0; + if(DoButton_Ex(&s_FlipXButton, "X/X", Enabled, &Button, 0, "[N] Flip brush horizontal", CUI::CORNER_L) || Input()->KeyDown('n')) { - for(int i = 0; i < brush.layers.len(); i++) - brush.layers[i]->brush_flip_x(); + for(int i = 0; i < m_Brush.m_lLayers.size(); i++) + m_Brush.m_lLayers[i]->BrushFlipX(); } - - toolbar.VSplitLeft(20.0f, &button, &toolbar); - static int flipy_button = 0; - if(DoButton_ButtonR(&flipy_button, "^Y", enabled, &button, 0, "[M] Flip brush vertical") || inp_key_down('m')) + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_FlipyButton = 0; + if(DoButton_Ex(&s_FlipyButton, "Y/Y", Enabled, &Button, 0, "[M] Flip brush vertical", CUI::CORNER_R) || Input()->KeyDown('m')) { - for(int i = 0; i < brush.layers.len(); i++) - brush.layers[i]->brush_flip_y(); + for(int i = 0; i < m_Brush.m_lLayers.size(); i++) + m_Brush.m_lLayers[i]->BrushFlipY(); } // rotate buttons - toolbar.VSplitLeft(20.0f, &button, &toolbar); - - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int rotation_amount = 90; - rotation_amount = ui_do_value_selector(&rotation_amount, &button, "", rotation_amount, 1, 360, 2.0f); - - toolbar.VSplitLeft(5.0f, &button, &toolbar); - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int ccw_button = 0; - if(DoButton_ButtonL(&ccw_button, "CCW", enabled, &button, 0, "[R] Rotates the brush counter clockwise") || inp_key_down('r')) + TB_Top.VSplitLeft(15.0f, &Button, &TB_Top); + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_RotationAmount = 90; + s_RotationAmount = UiDoValueSelector(&s_RotationAmount, &Button, "", s_RotationAmount, 1, 360, 2.0f); + + TB_Top.VSplitLeft(5.0f, &Button, &TB_Top); + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_CcwButton = 0; + if(DoButton_Ex(&s_CcwButton, "CCW", Enabled, &Button, 0, "[R] Rotates the brush counter clockwise", CUI::CORNER_L) || Input()->KeyDown('r')) { - for(int i = 0; i < brush.layers.len(); i++) - brush.layers[i]->brush_rotate(-rotation_amount/360.0f*pi*2); + for(int i = 0; i < m_Brush.m_lLayers.size(); i++) + m_Brush.m_lLayers[i]->BrushRotate(-s_RotationAmount/360.0f*pi*2); } - - toolbar.VSplitLeft(30.0f, &button, &toolbar); - static int cw_button = 0; - if(DoButton_ButtonR(&cw_button, "CW", enabled, &button, 0, "[T] Rotates the brush clockwise") || inp_key_down('t')) + + TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); + static int s_CwButton = 0; + if(DoButton_Ex(&s_CwButton, "CW", Enabled, &Button, 0, "[T] Rotates the brush clockwise", CUI::CORNER_R) || Input()->KeyDown('t')) { - for(int i = 0; i < brush.layers.len(); i++) - brush.layers[i]->brush_rotate(rotation_amount/360.0f*pi*2); + for(int i = 0; i < m_Brush.m_lLayers.size(); i++) + m_Brush.m_lLayers[i]->BrushRotate(s_RotationAmount/360.0f*pi*2); } } // quad manipulation { // do add button - toolbar.VSplitLeft(10.0f, &button, &toolbar); - toolbar.VSplitLeft(60.0f, &button, &toolbar); - static int new_button = 0; - - LAYER_QUADS *qlayer = (LAYER_QUADS *)get_selected_layer_type(0, LAYERTYPE_QUADS); - //LAYER_TILES *tlayer = (LAYER_TILES *)get_selected_layer_type(0, LAYERTYPE_TILES); - if(DoButton_Editor(&new_button, "Add Quad", qlayer?0:-1, &button, 0, "Adds a new quad")) + TB_Top.VSplitLeft(10.0f, &Button, &TB_Top); + TB_Top.VSplitLeft(60.0f, &Button, &TB_Top); + static int s_NewButton = 0; + + CLayerQuads *pQLayer = (CLayerQuads *)GetSelectedLayerType(0, LAYERTYPE_QUADS); + //CLayerTiles *tlayer = (CLayerTiles *)get_selected_layer_type(0, LAYERTYPE_TILES); + if(DoButton_Editor(&s_NewButton, "Add Quad", pQLayer?0:-1, &Button, 0, "Adds a new quad")) { - if(qlayer) + if(pQLayer) { - float mapping[4]; - LAYERGROUP *g = get_selected_group(); - g->mapping(mapping); - int add_x = f2fx(mapping[0] + (mapping[2]-mapping[0])/2); - int add_y = f2fx(mapping[1] + (mapping[3]-mapping[1])/2); - - QUAD *q = qlayer->new_quad(); + float Mapping[4]; + CLayerGroup *g = GetSelectedGroup(); + g->Mapping(Mapping); + int AddX = f2fx(Mapping[0] + (Mapping[2]-Mapping[0])/2); + int AddY = f2fx(Mapping[1] + (Mapping[3]-Mapping[1])/2); + + CQuad *q = pQLayer->NewQuad(); for(int i = 0; i < 5; i++) { - q->points[i].x += add_x; - q->points[i].y += add_y; + q->m_aPoints[i].x += AddX; + q->m_aPoints[i].y += AddY; } } } } + + // tile manipulation + { + TB_Bottom.VSplitLeft(40.0f, &Button, &TB_Bottom); + static int s_BorderBut = 0; + CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); + + if(DoButton_Editor(&s_BorderBut, "Border", pT?0:-1, &Button, 0, "Border")) + { + if(pT) + DoMapBorder(); + } + } } -static void rotate(POINT *center, POINT *point, float rotation) +static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation) { - int x = point->x - center->x; - int y = point->y - center->y; - point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x); - point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y); + int x = pPoint->x - pCenter->x; + int y = pPoint->y - pCenter->y; + pPoint->x = (int)(x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x); + pPoint->y = (int)(x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y); } -void EDITOR::do_quad(QUAD *q, int index) +void CEditor::DoQuad(CQuad *q, int Index) { enum { @@ -906,71 +775,72 @@ void EDITOR::do_quad(QUAD *q, int index) OP_ROTATE, OP_CONTEXT_MENU, }; - + // some basic values - void *id = &q->points[4]; // use pivot addr as id - static POINT rotate_points[4]; - static float last_wx; - static float last_wy; - static int operation = OP_NONE; - static float rotate_angle = 0; + void *pId = &q->m_aPoints[4]; // use pivot addr as id + static CPoint s_RotatePoints[4]; + static float s_LastWx; + static float s_LastWy; + static int s_Operation = OP_NONE; + static float s_RotateAngle = 0; float wx = UI()->MouseWorldX(); float wy = UI()->MouseWorldY(); - + // get pivot - float center_x = fx2f(q->points[4].x); - float center_y = fx2f(q->points[4].y); + float CenterX = fx2f(q->m_aPoints[4].x); + float CenterY = fx2f(q->m_aPoints[4].y); - float dx = (center_x - wx); - float dy = (center_y - wy); + float dx = (CenterX - wx); + float dy = (CenterY - wy); if(dx*dx+dy*dy < 10*10) - UI()->SetHotItem(id); + UI()->SetHotItem(pId); - // draw selection background - if(selected_quad == index) + // draw selection background + if(m_SelectedQuad == Index) { Graphics()->SetColor(0,0,0,1); - Graphics()->QuadsDraw(center_x, center_y, 7.0f, 7.0f); + IGraphics::CQuadItem QuadItem(CenterX, CenterY, 7.0f, 7.0f); + Graphics()->QuadsDraw(&QuadItem, 1); } - - if(UI()->ActiveItem() == id) + + if(UI()->ActiveItem() == pId) { // check if we only should move pivot - if(operation == OP_MOVE_PIVOT) + if(s_Operation == OP_MOVE_PIVOT) { - q->points[4].x += f2fx(wx-last_wx); - q->points[4].y += f2fx(wy-last_wy); + q->m_aPoints[4].x += f2fx(wx-s_LastWx); + q->m_aPoints[4].y += f2fx(wy-s_LastWy); } - else if(operation == OP_MOVE_ALL) + else if(s_Operation == OP_MOVE_ALL) { // move all points including pivot for(int v = 0; v < 5; v++) { - q->points[v].x += f2fx(wx-last_wx); - q->points[v].y += f2fx(wy-last_wy); + q->m_aPoints[v].x += f2fx(wx-s_LastWx); + q->m_aPoints[v].y += f2fx(wy-s_LastWy); } } - else if(operation == OP_ROTATE) + else if(s_Operation == OP_ROTATE) { for(int v = 0; v < 4; v++) { - q->points[v] = rotate_points[v]; - rotate(&q->points[4], &q->points[v], rotate_angle); + q->m_aPoints[v] = s_RotatePoints[v]; + Rotate(&q->m_aPoints[4], &q->m_aPoints[v], s_RotateAngle); } } - - rotate_angle += (mouse_delta_x) * 0.002f; - last_wx = wx; - last_wy = wy; - - if(operation == OP_CONTEXT_MENU) + + s_RotateAngle += (m_MouseDeltaX) * 0.002f; + s_LastWx = wx; + s_LastWy = wy; + + if(s_Operation == OP_CONTEXT_MENU) { if(!UI()->MouseButton(1)) { - static int quad_popup_id = 0; - ui_invoke_popup_menu(&quad_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_quad); - lock_mouse = false; - operation = OP_NONE; + static int s_QuadPopupId = 0; + UiInvokePopupMenu(&s_QuadPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupQuad); + m_LockMouse = false; + s_Operation = OP_NONE; UI()->SetActiveItem(0); } } @@ -978,79 +848,81 @@ void EDITOR::do_quad(QUAD *q, int index) { if(!UI()->MouseButton(0)) { - lock_mouse = false; - operation = OP_NONE; + m_LockMouse = false; + s_Operation = OP_NONE; UI()->SetActiveItem(0); } - } + } Graphics()->SetColor(1,1,1,1); } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) { - ui_got_context = id; - + ms_pUiGotContext = pId; + Graphics()->SetColor(1,1,1,1); - tooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate"; - + m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate"; + if(UI()->MouseButton(0)) { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - operation = OP_MOVE_PIVOT; - else if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL)) + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + s_Operation = OP_MOVE_PIVOT; + else if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)) { - lock_mouse = true; - operation = OP_ROTATE; - rotate_angle = 0; - rotate_points[0] = q->points[0]; - rotate_points[1] = q->points[1]; - rotate_points[2] = q->points[2]; - rotate_points[3] = q->points[3]; + m_LockMouse = true; + s_Operation = OP_ROTATE; + s_RotateAngle = 0; + s_RotatePoints[0] = q->m_aPoints[0]; + s_RotatePoints[1] = q->m_aPoints[1]; + s_RotatePoints[2] = q->m_aPoints[2]; + s_RotatePoints[3] = q->m_aPoints[3]; } else - operation = OP_MOVE_ALL; - - UI()->SetActiveItem(id); - selected_quad = index; - last_wx = wx; - last_wy = wy; + s_Operation = OP_MOVE_ALL; + + UI()->SetActiveItem(pId); + m_SelectedQuad = Index; + s_LastWx = wx; + s_LastWy = wy; } - + if(UI()->MouseButton(1)) { - selected_quad = index; - operation = OP_CONTEXT_MENU; - UI()->SetActiveItem(id); + m_SelectedQuad = Index; + s_Operation = OP_CONTEXT_MENU; + UI()->SetActiveItem(pId); } } else Graphics()->SetColor(0,1,0,1); - Graphics()->QuadsDraw(center_x, center_y, 5.0f, 5.0f); + IGraphics::CQuadItem QuadItem(CenterX, CenterY, 5.0f, 5.0f); + Graphics()->QuadsDraw(&QuadItem, 1); } -void EDITOR::do_quad_point(QUAD *q, int quad_index, int v) +void CEditor::DoQuadPoint(CQuad *q, int QuadIndex, int v) { - void *id = &q->points[v]; + void *pId = &q->m_aPoints[v]; float wx = UI()->MouseWorldX(); float wy = UI()->MouseWorldY(); - - float px = fx2f(q->points[v].x); - float py = fx2f(q->points[v].y); - + + float px = fx2f(q->m_aPoints[v].x); + float py = fx2f(q->m_aPoints[v].y); + float dx = (px - wx); float dy = (py - wy); if(dx*dx+dy*dy < 10*10) - UI()->SetHotItem(id); + UI()->SetHotItem(pId); - // draw selection background - if(selected_quad == quad_index && selected_points&(1<<v)) + // draw selection background + if(m_SelectedQuad == QuadIndex && m_SelectedPoints&(1<<v)) { Graphics()->SetColor(0,0,0,1); - Graphics()->QuadsDraw(px, py, 7.0f, 7.0f); + IGraphics::CQuadItem QuadItem(px, py, 7.0f, 7.0f); + Graphics()->QuadsDraw(&QuadItem, 1); } - + enum { OP_NONE=0, @@ -1058,48 +930,48 @@ void EDITOR::do_quad_point(QUAD *q, int quad_index, int v) OP_MOVEUV, OP_CONTEXT_MENU }; - - static bool moved; - static int operation = OP_NONE; - if(UI()->ActiveItem() == id) + static bool s_Moved; + static int s_Operation = OP_NONE; + + if(UI()->ActiveItem() == pId) { - float dx = mouse_delta_wx; - float dy = mouse_delta_wy; - if(!moved) + float dx = m_MouseDeltaWx; + float dy = m_MouseDeltaWy; + if(!s_Moved) { if(dx*dx+dy*dy > 0.5f) - moved = true; + s_Moved = true; } - - if(moved) + + if(s_Moved) { - if(operation == OP_MOVEPOINT) + if(s_Operation == OP_MOVEPOINT) { for(int m = 0; m < 4; m++) - if(selected_points&(1<<m)) + if(m_SelectedPoints&(1<<m)) { - q->points[m].x += f2fx(dx); - q->points[m].y += f2fx(dy); + q->m_aPoints[m].x += f2fx(dx); + q->m_aPoints[m].y += f2fx(dy); } } - else if(operation == OP_MOVEUV) + else if(s_Operation == OP_MOVEUV) { for(int m = 0; m < 4; m++) - if(selected_points&(1<<m)) + if(m_SelectedPoints&(1<<m)) { - q->texcoords[m].x += f2fx(dx*0.001f); - q->texcoords[m].y += f2fx(dy*0.001f); + q->m_aTexcoords[m].x += f2fx(dx*0.001f); + q->m_aTexcoords[m].y += f2fx(dy*0.001f); } } } - - if(operation == OP_CONTEXT_MENU) + + if(s_Operation == OP_CONTEXT_MENU) { if(!UI()->MouseButton(1)) { - static int point_popup_id = 0; - ui_invoke_popup_menu(&point_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_point); + static int s_PointPopupId = 0; + UiInvokePopupMenu(&s_PointPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupPoint); UI()->SetActiveItem(0); } } @@ -1107,210 +979,214 @@ void EDITOR::do_quad_point(QUAD *q, int quad_index, int v) { if(!UI()->MouseButton(0)) { - if(!moved) + if(!s_Moved) { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - selected_points ^= 1<<v; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + m_SelectedPoints ^= 1<<v; else - selected_points = 1<<v; + m_SelectedPoints = 1<<v; } - lock_mouse = false; + m_LockMouse = false; UI()->SetActiveItem(0); } } Graphics()->SetColor(1,1,1,1); } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) { - ui_got_context = id; - + ms_pUiGotContext = pId; + Graphics()->SetColor(1,1,1,1); - tooltip = "Left mouse button to move. Hold shift to move the texture."; - + m_pTooltip = "Left mouse button to move. Hold shift to move the texture."; + if(UI()->MouseButton(0)) { - UI()->SetActiveItem(id); - moved = false; - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) + UI()->SetActiveItem(pId); + s_Moved = false; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) { - operation = OP_MOVEUV; - lock_mouse = true; + s_Operation = OP_MOVEUV; + m_LockMouse = true; } else - operation = OP_MOVEPOINT; - - if(!(selected_points&(1<<v))) + s_Operation = OP_MOVEPOINT; + + if(!(m_SelectedPoints&(1<<v))) { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - selected_points |= 1<<v; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + m_SelectedPoints |= 1<<v; else - selected_points = 1<<v; - moved = true; + m_SelectedPoints = 1<<v; + s_Moved = true; } - - selected_quad = quad_index; + + m_SelectedQuad = QuadIndex; } else if(UI()->MouseButton(1)) { - operation = OP_CONTEXT_MENU; - selected_quad = quad_index; - UI()->SetActiveItem(id); + s_Operation = OP_CONTEXT_MENU; + m_SelectedQuad = QuadIndex; + UI()->SetActiveItem(pId); } } else Graphics()->SetColor(1,0,0,1); - - Graphics()->QuadsDraw(px, py, 5.0f, 5.0f); + + IGraphics::CQuadItem QuadItem(px, py, 5.0f, 5.0f); + Graphics()->QuadsDraw(&QuadItem, 1); } -void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar) +void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { //UI()->ClipEnable(&view); - - bool show_picker = inp_key_pressed(KEY_SPACE) != 0 && dialog == DIALOG_NONE; + + bool ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE; // render all good stuff - if(!show_picker) + if(!ShowPicker) { - for(int g = 0; g < map.groups.len(); g++) + for(int g = 0; g < m_Map.m_lGroups.size(); g++) { - if(map.groups[g]->visible) - map.groups[g]->render(); + if(m_Map.m_lGroups[g]->m_Visible) + m_Map.m_lGroups[g]->Render(); //UI()->ClipEnable(&view); } - + // render the game above everything else - if(map.game_group->visible && map.game_layer->visible) + if(m_Map.m_pGameGroup->m_Visible && m_Map.m_pGameLayer->m_Visible) { - map.game_group->mapscreen(); - map.game_layer->render(); + m_Map.m_pGameGroup->MapScreen(); + m_Map.m_pGameLayer->Render(); } } - static void *editor_id = (void *)&editor_id; - int inside = UI()->MouseInside(&view); + static void *s_pEditorId = (void *)&s_pEditorId; + int Inside = UI()->MouseInside(&View); // fetch mouse position float wx = UI()->MouseWorldX(); float wy = UI()->MouseWorldY(); float mx = UI()->MouseX(); float my = UI()->MouseY(); - - static float start_wx = 0; - static float start_wy = 0; - static float start_mx = 0; - static float start_my = 0; - + + static float s_StartWx = 0; + static float s_StartWy = 0; + static float s_StartMx = 0; + static float s_StartMy = 0; + enum { OP_NONE=0, OP_BRUSH_GRAB, OP_BRUSH_DRAW, + OP_BRUSH_PAINT, OP_PAN_WORLD, OP_PAN_EDITOR, }; // remap the screen so it can display the whole tileset - if(show_picker) - { - CUIRect screen = *UI()->Screen(); - float size = 32.0*16.0f; - float w = size*(screen.w/view.w); - float h = size*(screen.h/view.h); - float x = -(view.x/screen.w)*w; - float y = -(view.y/screen.h)*h; - wx = x+w*mx/screen.w; - wy = y+h*my/screen.h; + if(ShowPicker) + { + CUIRect Screen = *UI()->Screen(); + float Size = 32.0*16.0f; + float w = Size*(Screen.w/View.w); + float h = Size*(Screen.h/View.h); + float x = -(View.x/Screen.w)*w; + float y = -(View.y/Screen.h)*h; + wx = x+w*mx/Screen.w; + wy = y+h*my/Screen.h; Graphics()->MapScreen(x, y, x+w, y+h); - LAYER_TILES *t = (LAYER_TILES *)get_selected_layer_type(0, LAYERTYPE_TILES); + CLayerTiles *t = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); if(t) { - tileset_picker.image = t->image; - tileset_picker.tex_id = t->tex_id; - tileset_picker.render(); + m_TilesetPicker.m_Image = t->m_Image; + m_TilesetPicker.m_TexId = t->m_TexId; + m_TilesetPicker.Render(); } } - - static int operation = OP_NONE; - + + static int s_Operation = OP_NONE; + // draw layer borders - LAYER *edit_layers[16]; - int num_edit_layers = 0; - num_edit_layers = 0; - - if(show_picker) + CLayer *pEditLayers[16]; + int NumEditLayers = 0; + NumEditLayers = 0; + + if(ShowPicker) { - edit_layers[0] = &tileset_picker; - num_edit_layers++; + pEditLayers[0] = &m_TilesetPicker; + NumEditLayers++; } else { - edit_layers[0] = get_selected_layer(0); - if(edit_layers[0]) - num_edit_layers++; + pEditLayers[0] = GetSelectedLayer(0); + if(pEditLayers[0]) + NumEditLayers++; - LAYERGROUP *g = get_selected_group(); + CLayerGroup *g = GetSelectedGroup(); if(g) { - g->mapscreen(); - - for(int i = 0; i < num_edit_layers; i++) + g->MapScreen(); + + for(int i = 0; i < NumEditLayers; i++) { - if(edit_layers[i]->type != LAYERTYPE_TILES) + if(pEditLayers[i]->m_Type != LAYERTYPE_TILES) continue; - + float w, h; - edit_layers[i]->get_size(&w, &h); + pEditLayers[i]->GetSize(&w, &h); + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(0, 0, w, 0), + IGraphics::CLineItem(w, 0, w, h), + IGraphics::CLineItem(w, h, 0, h), + IGraphics::CLineItem(0, h, 0, 0)}; Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - Graphics()->LinesDraw(0,0, w,0); - Graphics()->LinesDraw(w,0, w,h); - Graphics()->LinesDraw(w,h, 0,h); - Graphics()->LinesDraw(0,h, 0,0); + Graphics()->LinesDraw(Array, 4); Graphics()->LinesEnd(); } } } - - if(inside) + + if(Inside) { - UI()->SetHotItem(editor_id); - + UI()->SetHotItem(s_pEditorId); + // do global operations like pan and zoom if(UI()->ActiveItem() == 0 && (UI()->MouseButton(0) || UI()->MouseButton(2))) { - start_wx = wx; - start_wy = wy; - start_mx = mx; - start_my = my; - - if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL) || UI()->MouseButton(2)) + s_StartWx = wx; + s_StartWy = wy; + s_StartMx = mx; + s_StartMy = my; + + if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL) || UI()->MouseButton(2)) { - if(inp_key_pressed(KEY_LSHIFT)) - operation = OP_PAN_EDITOR; + if(Input()->KeyPressed(KEY_LSHIFT)) + s_Operation = OP_PAN_EDITOR; else - operation = OP_PAN_WORLD; - UI()->SetActiveItem(editor_id); + s_Operation = OP_PAN_WORLD; + UI()->SetActiveItem(s_pEditorId); } } // brush editing - if(UI()->HotItem() == editor_id) + if(UI()->HotItem() == s_pEditorId) { - if(brush.is_empty()) - tooltip = "Use left mouse button to drag and create a brush."; + if(m_Brush.IsEmpty()) + m_pTooltip = "Use left mouse button to drag and create a brush."; else - tooltip = "Use left mouse button to paint with the brush. Right button clears the brush."; + m_pTooltip = "Use left mouse button to paint with the brush. Right button clears the brush."; - if(UI()->ActiveItem() == editor_id) + if(UI()->ActiveItem() == s_pEditorId) { CUIRect r; - r.x = start_wx; - r.y = start_wy; - r.w = wx-start_wx; - r.h = wy-start_wy; + r.x = s_StartWx; + r.y = s_StartWy; + r.w = wx-s_StartWx; + r.h = wy-s_StartWy; if(r.w < 0) { r.x += r.w; @@ -1322,38 +1198,53 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar) r.y += r.h; r.h = -r.h; } - - if(operation == OP_BRUSH_DRAW) - { - if(!brush.is_empty()) + + if(s_Operation == OP_BRUSH_DRAW) + { + if(!m_Brush.IsEmpty()) { // draw with brush - for(int k = 0; k < num_edit_layers; k++) + for(int k = 0; k < NumEditLayers; k++) { - if(edit_layers[k]->type == brush.layers[0]->type) - edit_layers[k]->brush_draw(brush.layers[0], wx, wy); + if(pEditLayers[k]->m_Type == m_Brush.m_lLayers[0]->m_Type) + pEditLayers[k]->BrushDraw(m_Brush.m_lLayers[0], wx, wy); } } } - else if(operation == OP_BRUSH_GRAB) + else if(s_Operation == OP_BRUSH_GRAB) { if(!UI()->MouseButton(0)) { // grab brush dbg_msg("editor", "grabbing %f %f %f %f", r.x, r.y, r.w, r.h); - + // TODO: do all layers - int grabs = 0; - for(int k = 0; k < num_edit_layers; k++) - grabs += edit_layers[k]->brush_grab(&brush, r); - if(grabs == 0) - brush.clear(); + int Grabs = 0; + for(int k = 0; k < NumEditLayers; k++) + Grabs += pEditLayers[k]->BrushGrab(&m_Brush, r); + if(Grabs == 0) + m_Brush.Clear(); } else { //editor.map.groups[selected_group]->mapscreen(); - for(int k = 0; k < num_edit_layers; k++) - edit_layers[k]->brush_selecting(r); + for(int k = 0; k < NumEditLayers; k++) + pEditLayers[k]->BrushSelecting(r); + Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); + } + } + else if(s_Operation == OP_BRUSH_PAINT) + { + if(!UI()->MouseButton(0)) + { + for(int k = 0; k < NumEditLayers; k++) + pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r); + } + else + { + //editor.map.groups[selected_group]->mapscreen(); + for(int k = 0; k < NumEditLayers; k++) + pEditLayers[k]->BrushSelecting(r); Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); } } @@ -1361,182 +1252,196 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar) else { if(UI()->MouseButton(1)) - brush.clear(); - - if(UI()->MouseButton(0) && operation == OP_NONE) + m_Brush.Clear(); + + if(UI()->MouseButton(0) && s_Operation == OP_NONE) { - UI()->SetActiveItem(editor_id); - - if(brush.is_empty()) - operation = OP_BRUSH_GRAB; + UI()->SetActiveItem(s_pEditorId); + + if(m_Brush.IsEmpty()) + s_Operation = OP_BRUSH_GRAB; else { - operation = OP_BRUSH_DRAW; - for(int k = 0; k < num_edit_layers; k++) + s_Operation = OP_BRUSH_DRAW; + for(int k = 0; k < NumEditLayers; k++) { - if(edit_layers[k]->type == brush.layers[0]->type) - edit_layers[k]->brush_place(brush.layers[0], wx, wy); + if(pEditLayers[k]->m_Type == m_Brush.m_lLayers[0]->m_Type) + pEditLayers[k]->BrushPlace(m_Brush.m_lLayers[0], wx, wy); } - + } + + CLayerTiles *pLayer = (CLayerTiles*)GetSelectedLayerType(0, LAYERTYPE_TILES); + if((Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) && pLayer) + s_Operation = OP_BRUSH_PAINT; } - - if(!brush.is_empty()) + + if(!m_Brush.IsEmpty()) { - brush.offset_x = -(int)wx; - brush.offset_y = -(int)wy; - for(int i = 0; i < brush.layers.len(); i++) + m_Brush.m_OffsetX = -(int)wx; + m_Brush.m_OffsetY = -(int)wy; + for(int i = 0; i < m_Brush.m_lLayers.size(); i++) { - if(brush.layers[i]->type == LAYERTYPE_TILES) + if(m_Brush.m_lLayers[i]->m_Type == LAYERTYPE_TILES) { - brush.offset_x = -(int)(wx/32.0f)*32; - brush.offset_y = -(int)(wy/32.0f)*32; + m_Brush.m_OffsetX = -(int)(wx/32.0f)*32; + m_Brush.m_OffsetY = -(int)(wy/32.0f)*32; break; } } - - LAYERGROUP *g = get_selected_group(); - brush.offset_x += g->offset_x; - brush.offset_y += g->offset_y; - brush.parallax_x = g->parallax_x; - brush.parallax_y = g->parallax_y; - brush.render(); + + CLayerGroup *g = GetSelectedGroup(); + m_Brush.m_OffsetX += g->m_OffsetX; + m_Brush.m_OffsetY += g->m_OffsetY; + m_Brush.m_ParallaxX = g->m_ParallaxX; + m_Brush.m_ParallaxY = g->m_ParallaxY; + m_Brush.Render(); float w, h; - brush.get_size(&w, &h); - + m_Brush.GetSize(&w, &h); + + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(0, 0, w, 0), + IGraphics::CLineItem(w, 0, w, h), + IGraphics::CLineItem(w, h, 0, h), + IGraphics::CLineItem(0, h, 0, 0)}; Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - Graphics()->LinesDraw(0,0, w,0); - Graphics()->LinesDraw(w,0, w,h); - Graphics()->LinesDraw(w,h, 0,h); - Graphics()->LinesDraw(0,h, 0,0); + Graphics()->LinesDraw(Array, 4); Graphics()->LinesEnd(); - + } } } - + // quad editing { - if(!show_picker && brush.is_empty()) + if(!ShowPicker && m_Brush.IsEmpty()) { // fetch layers - LAYERGROUP *g = get_selected_group(); + CLayerGroup *g = GetSelectedGroup(); if(g) - g->mapscreen(); - - for(int k = 0; k < num_edit_layers; k++) + g->MapScreen(); + + for(int k = 0; k < NumEditLayers; k++) { - if(edit_layers[k]->type == LAYERTYPE_QUADS) + if(pEditLayers[k]->m_Type == LAYERTYPE_QUADS) { - LAYER_QUADS *layer = (LAYER_QUADS *)edit_layers[k]; - + CLayerQuads *pLayer = (CLayerQuads *)pEditLayers[k]; + Graphics()->TextureSet(-1); - Graphics()->QuadsBegin(); - for(int i = 0; i < layer->quads.len(); i++) + Graphics()->QuadsBegin(); + for(int i = 0; i < pLayer->m_lQuads.size(); i++) { for(int v = 0; v < 4; v++) - do_quad_point(&layer->quads[i], i, v); - - do_quad(&layer->quads[i], i); + DoQuadPoint(&pLayer->m_lQuads[i], i, v); + + DoQuad(&pLayer->m_lQuads[i], i); } Graphics()->QuadsEnd(); } } - + Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); - } - + } + // do panning - if(UI()->ActiveItem() == editor_id) + if(UI()->ActiveItem() == s_pEditorId) { - if(operation == OP_PAN_WORLD) + if(s_Operation == OP_PAN_WORLD) { - world_offset_x -= mouse_delta_x*world_zoom; - world_offset_y -= mouse_delta_y*world_zoom; + m_WorldOffsetX -= m_MouseDeltaX*m_WorldZoom; + m_WorldOffsetY -= m_MouseDeltaY*m_WorldZoom; } - else if(operation == OP_PAN_EDITOR) + else if(s_Operation == OP_PAN_EDITOR) { - editor_offset_x -= mouse_delta_x*world_zoom; - editor_offset_y -= mouse_delta_y*world_zoom; + m_EditorOffsetX -= m_MouseDeltaX*m_WorldZoom; + m_EditorOffsetY -= m_MouseDeltaY*m_WorldZoom; } // release mouse if(!UI()->MouseButton(0)) { - operation = OP_NONE; + s_Operation = OP_NONE; UI()->SetActiveItem(0); } } } } - - if(get_selected_group() && get_selected_group()->use_clipping) + + if(GetSelectedGroup() && GetSelectedGroup()->m_UseClipping) { - LAYERGROUP *g = map.game_group; - g->mapscreen(); - + CLayerGroup *g = m_Map.m_pGameGroup; + g->MapScreen(); + Graphics()->TextureSet(-1); Graphics()->LinesBegin(); CUIRect r; - r.x = get_selected_group()->clip_x; - r.y = get_selected_group()->clip_y; - r.w = get_selected_group()->clip_w; - r.h = get_selected_group()->clip_h; - + r.x = GetSelectedGroup()->m_ClipX; + r.y = GetSelectedGroup()->m_ClipY; + r.w = GetSelectedGroup()->m_ClipW; + r.h = GetSelectedGroup()->m_ClipH; + + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(r.x, r.y, r.x+r.w, r.y), + IGraphics::CLineItem(r.x+r.w, r.y, r.x+r.w, r.y+r.h), + IGraphics::CLineItem(r.x+r.w, r.y+r.h, r.x, r.y+r.h), + IGraphics::CLineItem(r.x, r.y+r.h, r.x, r.y)}; Graphics()->SetColor(1,0,0,1); - Graphics()->LinesDraw(r.x, r.y, r.x+r.w, r.y); - Graphics()->LinesDraw(r.x+r.w, r.y, r.x+r.w, r.y+r.h); - Graphics()->LinesDraw(r.x+r.w, r.y+r.h, r.x, r.y+r.h); - Graphics()->LinesDraw(r.x, r.y+r.h, r.x, r.y); - + Graphics()->LinesDraw(Array, 4); + Graphics()->LinesEnd(); } - // render screen sizes - if(proof_borders) + // render screen sizes + if(m_ProofBorders) { - LAYERGROUP *g = map.game_group; - g->mapscreen(); - + CLayerGroup *g = m_Map.m_pGameGroup; + g->MapScreen(); + Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - - float last_points[4]; - float start = 1.0f; //9.0f/16.0f; - float end = 16.0f/9.0f; - const int num_steps = 20; - for(int i = 0; i <= num_steps; i++) + + float aLastPoints[4]; + float Start = 1.0f; //9.0f/16.0f; + float End = 16.0f/9.0f; + const int NumSteps = 20; + for(int i = 0; i <= NumSteps; i++) { - float points[4]; - float aspect = start + (end-start)*(i/(float)num_steps); - - RenderTools()->mapscreen_to_world( - world_offset_x, world_offset_y, - 1.0f, 1.0f, 0.0f, 0.0f, aspect, 1.0f, points); - + float aPoints[4]; + float Aspect = Start + (End-Start)*(i/(float)NumSteps); + + RenderTools()->MapscreenToWorld( + m_WorldOffsetX, m_WorldOffsetY, + 1.0f, 1.0f, 0.0f, 0.0f, Aspect, 1.0f, aPoints); + if(i == 0) { - Graphics()->LinesDraw(points[0], points[1], points[2], points[1]); - Graphics()->LinesDraw(points[0], points[3], points[2], points[3]); + IGraphics::CLineItem Array[2] = { + IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[2], aPoints[1]), + IGraphics::CLineItem(aPoints[0], aPoints[3], aPoints[2], aPoints[3])}; + Graphics()->LinesDraw(Array, 2); } if(i != 0) { - Graphics()->LinesDraw(points[0], points[1], last_points[0], last_points[1]); - Graphics()->LinesDraw(points[2], points[1], last_points[2], last_points[1]); - Graphics()->LinesDraw(points[0], points[3], last_points[0], last_points[3]); - Graphics()->LinesDraw(points[2], points[3], last_points[2], last_points[3]); + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(aPoints[0], aPoints[1], aLastPoints[0], aLastPoints[1]), + IGraphics::CLineItem(aPoints[2], aPoints[1], aLastPoints[2], aLastPoints[1]), + IGraphics::CLineItem(aPoints[0], aPoints[3], aLastPoints[0], aLastPoints[3]), + IGraphics::CLineItem(aPoints[2], aPoints[3], aLastPoints[2], aLastPoints[3])}; + Graphics()->LinesDraw(Array, 4); } - if(i == num_steps) + if(i == NumSteps) { - Graphics()->LinesDraw(points[0], points[1], points[0], points[3]); - Graphics()->LinesDraw(points[2], points[1], points[2], points[3]); + IGraphics::CLineItem Array[2] = { + IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[0], aPoints[3]), + IGraphics::CLineItem(aPoints[2], aPoints[1], aPoints[2], aPoints[3])}; + Graphics()->LinesDraw(Array, 2); } - - mem_copy(last_points, points, sizeof(points)); + + mem_copy(aLastPoints, aPoints, sizeof(aPoints)); } if(1) @@ -1544,351 +1449,359 @@ void EDITOR::do_map_editor(CUIRect view, CUIRect toolbar) Graphics()->SetColor(1,0,0,1); for(int i = 0; i < 2; i++) { - float points[4]; - float aspects[] = {4.0f/3.0f, 16.0f/10.0f, 5.0f/4.0f, 16.0f/9.0f}; - float aspect = aspects[i]; - - RenderTools()->mapscreen_to_world( - world_offset_x, world_offset_y, - 1.0f, 1.0f, 0.0f, 0.0f, aspect, 1.0f, points); - + float aPoints[4]; + float aAspects[] = {4.0f/3.0f, 16.0f/10.0f, 5.0f/4.0f, 16.0f/9.0f}; + float Aspect = aAspects[i]; + + RenderTools()->MapscreenToWorld( + m_WorldOffsetX, m_WorldOffsetY, + 1.0f, 1.0f, 0.0f, 0.0f, Aspect, 1.0f, aPoints); + CUIRect r; - r.x = points[0]; - r.y = points[1]; - r.w = points[2]-points[0]; - r.h = points[3]-points[1]; - - Graphics()->LinesDraw(r.x, r.y, r.x+r.w, r.y); - Graphics()->LinesDraw(r.x+r.w, r.y, r.x+r.w, r.y+r.h); - Graphics()->LinesDraw(r.x+r.w, r.y+r.h, r.x, r.y+r.h); - Graphics()->LinesDraw(r.x, r.y+r.h, r.x, r.y); + r.x = aPoints[0]; + r.y = aPoints[1]; + r.w = aPoints[2]-aPoints[0]; + r.h = aPoints[3]-aPoints[1]; + + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(r.x, r.y, r.x+r.w, r.y), + IGraphics::CLineItem(r.x+r.w, r.y, r.x+r.w, r.y+r.h), + IGraphics::CLineItem(r.x+r.w, r.y+r.h, r.x, r.y+r.h), + IGraphics::CLineItem(r.x, r.y+r.h, r.x, r.y)}; + Graphics()->LinesDraw(Array, 4); Graphics()->SetColor(0,1,0,1); } } - + Graphics()->LinesEnd(); } - + Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); //UI()->ClipDisable(); } -int EDITOR::do_properties(CUIRect *toolbox, PROPERTY *props, int *ids, int *new_val) +int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIds, int *pNewVal) { - int change = -1; + int Change = -1; - for(int i = 0; props[i].name; i++) + for(int i = 0; pProps[i].m_pName; i++) { - CUIRect slot; - toolbox->HSplitTop(13.0f, &slot, toolbox); - CUIRect label, shifter; - slot.VSplitMid(&label, &shifter); - shifter.HMargin(1.0f, &shifter); - UI()->DoLabel(&label, props[i].name, 10.0f, -1, -1); - - if(props[i].type == PROPTYPE_INT_STEP) + CUIRect Slot; + pToolBox->HSplitTop(13.0f, &Slot, pToolBox); + CUIRect Label, Shifter; + Slot.VSplitMid(&Label, &Shifter); + Shifter.HMargin(1.0f, &Shifter); + UI()->DoLabel(&Label, pProps[i].m_pName, 10.0f, -1, -1); + + if(pProps[i].m_Type == PROPTYPE_INT_STEP) { - CUIRect inc, dec; - char buf[64]; - - shifter.VSplitRight(10.0f, &shifter, &inc); - shifter.VSplitLeft(10.0f, &dec, &shifter); - sprintf(buf, "%d", props[i].value); - RenderTools()->DrawUIRect(&shifter, vec4(1,1,1,0.5f), 0, 0.0f); - UI()->DoLabel(&shifter, buf, 10.0f, 0, -1); - - if(DoButton_ButtonDec(&ids[i], 0, 0, &dec, 0, "Decrease")) + CUIRect Inc, Dec; + char aBuf[64]; + + Shifter.VSplitRight(10.0f, &Shifter, &Inc); + Shifter.VSplitLeft(10.0f, &Dec, &Shifter); + str_format(aBuf, sizeof(aBuf),"%d", pProps[i].m_Value); + RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f); + UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1); + + if(DoButton_ButtonDec(&pIds[i], 0, 0, &Dec, 0, "Decrease")) { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - *new_val = props[i].value-5; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + *pNewVal = pProps[i].m_Value-5; else - *new_val = props[i].value-1; - change = i; + *pNewVal = pProps[i].m_Value-1; + Change = i; } - if(DoButton_ButtonInc(((char *)&ids[i])+1, 0, 0, &inc, 0, "Increase")) + if(DoButton_ButtonInc(((char *)&pIds[i])+1, 0, 0, &Inc, 0, "Increase")) { - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) - *new_val = props[i].value+5; + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) + *pNewVal = pProps[i].m_Value+5; else - *new_val = props[i].value+1; - change = i; + *pNewVal = pProps[i].m_Value+1; + Change = i; } } - else if(props[i].type == PROPTYPE_BOOL) + else if(pProps[i].m_Type == PROPTYPE_BOOL) { - CUIRect no, yes; - shifter.VSplitMid(&no, &yes); - if(DoButton_ButtonDec(&ids[i], "No", !props[i].value, &no, 0, "")) + CUIRect No, Yes; + Shifter.VSplitMid(&No, &Yes); + if(DoButton_ButtonDec(&pIds[i], "No", !pProps[i].m_Value, &No, 0, "")) { - *new_val = 0; - change = i; + *pNewVal = 0; + Change = i; } - if(DoButton_ButtonInc(((char *)&ids[i])+1, "Yes", props[i].value, &yes, 0, "")) + if(DoButton_ButtonInc(((char *)&pIds[i])+1, "Yes", pProps[i].m_Value, &Yes, 0, "")) { - *new_val = 1; - change = i; + *pNewVal = 1; + Change = i; } - } - else if(props[i].type == PROPTYPE_INT_SCROLL) + } + else if(pProps[i].m_Type == PROPTYPE_INT_SCROLL) { - int new_value = ui_do_value_selector(&ids[i], &shifter, "", props[i].value, props[i].min, props[i].max, 1.0f); - if(new_value != props[i].value) + int NewValue = UiDoValueSelector(&pIds[i], &Shifter, "", pProps[i].m_Value, pProps[i].m_Min, pProps[i].m_Max, 1.0f); + if(NewValue != pProps[i].m_Value) { - *new_val = new_value; - change = i; + *pNewVal = NewValue; + Change = i; } } - else if(props[i].type == PROPTYPE_COLOR) + else if(pProps[i].m_Type == PROPTYPE_COLOR) { - static const char *texts[4] = {"R", "G", "B", "A"}; - static int shift[] = {24, 16, 8, 0}; - int new_color = 0; - + static const char *s_paTexts[4] = {"R", "G", "B", "A"}; + static int s_aShift[] = {24, 16, 8, 0}; + int NewColor = 0; + for(int c = 0; c < 4; c++) { - int v = (props[i].value >> shift[c])&0xff; - new_color |= ui_do_value_selector(((char *)&ids[i])+c, &shifter, texts[c], v, 0, 255, 1.0f)<<shift[c]; + int v = (pProps[i].m_Value >> s_aShift[c])&0xff; + NewColor |= UiDoValueSelector(((char *)&pIds[i])+c, &Shifter, s_paTexts[c], v, 0, 255, 1.0f)<<s_aShift[c]; if(c != 3) { - toolbox->HSplitTop(13.0f, &slot, toolbox); - slot.VSplitMid(0, &shifter); - shifter.HMargin(1.0f, &shifter); + pToolBox->HSplitTop(13.0f, &Slot, pToolBox); + Slot.VSplitMid(0, &Shifter); + Shifter.HMargin(1.0f, &Shifter); } } - - if(new_color != props[i].value) + + if(NewColor != pProps[i].m_Value) { - *new_val = new_color; - change = i; + *pNewVal = NewColor; + Change = i; } } - else if(props[i].type == PROPTYPE_IMAGE) + else if(pProps[i].m_Type == PROPTYPE_IMAGE) { - char buf[64]; - if(props[i].value < 0) - strcpy(buf, "None"); + char aBuf[64]; + if(pProps[i].m_Value < 0) + str_copy(aBuf, "None", sizeof(aBuf)); else - sprintf(buf, "%s", map.images[props[i].value]->name); - - if(DoButton_Editor(&ids[i], buf, 0, &shifter, 0, 0)) - popup_select_image_invoke(props[i].value, UI()->MouseX(), UI()->MouseY()); - - int r = popup_select_image_result(); + str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Value]->m_aName); + + if(DoButton_Editor(&pIds[i], aBuf, 0, &Shifter, 0, 0)) + PopupSelectImageInvoke(pProps[i].m_Value, UI()->MouseX(), UI()->MouseY()); + + int r = PopupSelectImageResult(); if(r >= -1) { - *new_val = r; - change = i; + *pNewVal = r; + Change = i; } } } - return change; + return Change; } -void EDITOR::render_layers(CUIRect toolbox, CUIRect toolbar, CUIRect view) +void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) { - CUIRect layersbox = toolbox; + CUIRect LayersBox = ToolBox; - if(!gui_active) + if(!m_GuiActive) return; - - CUIRect slot, button; - char buf[64]; - int valid_group = 0; - int valid_layer = 0; - if(selected_group >= 0 && selected_group < map.groups.len()) - valid_group = 1; + CUIRect Slot, Button; + char aBuf[64]; - if(valid_group && selected_layer >= 0 && selected_layer < map.groups[selected_group]->layers.len()) - valid_layer = 1; - - // render layers + int ValidGroup = 0; + int ValidLayer = 0; + if(m_SelectedGroup >= 0 && m_SelectedGroup < m_Map.m_lGroups.size()) + ValidGroup = 1; + + if(ValidGroup && m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size()) + ValidLayer = 1; + + // render layers { - for(int g = 0; g < map.groups.len(); g++) + for(int g = 0; g < m_Map.m_lGroups.size(); g++) { - CUIRect visible_toggle; - layersbox.HSplitTop(12.0f, &slot, &layersbox); - slot.VSplitLeft(12, &visible_toggle, &slot); - if(DoButton_ButtonL(&map.groups[g]->visible, map.groups[g]->visible?"V":"H", 0, &visible_toggle, 0, "Toggle group visibility")) - map.groups[g]->visible = !map.groups[g]->visible; - - sprintf(buf, "#%d %s", g, map.groups[g]->name); - if(int result = DoButton_ButtonR(&map.groups[g], buf, g==selected_group, &slot, - BUTTON_CONTEXT, "Select group. Right click for properties.")) + CUIRect VisibleToggle; + LayersBox.HSplitTop(12.0f, &Slot, &LayersBox); + Slot.VSplitLeft(12, &VisibleToggle, &Slot); + if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle group visibility", CUI::CORNER_L)) + m_Map.m_lGroups[g]->m_Visible = !m_Map.m_lGroups[g]->m_Visible; + + str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_pName); + if(int Result = DoButton_Ex(&m_Map.m_lGroups[g], aBuf, g==m_SelectedGroup, &Slot, + BUTTON_CONTEXT, "Select group. Right click for properties.", CUI::CORNER_R)) { - selected_group = g; - selected_layer = 0; - - static int group_popup_id = 0; - if(result == 2) - ui_invoke_popup_menu(&group_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, popup_group); + m_SelectedGroup = g; + m_SelectedLayer = 0; + + static int s_GroupPopupId = 0; + if(Result == 2) + UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupGroup); } - - - layersbox.HSplitTop(2.0f, &slot, &layersbox); - - for(int i = 0; i < map.groups[g]->layers.len(); i++) + + LayersBox.HSplitTop(2.0f, &Slot, &LayersBox); + + for(int i = 0; i < m_Map.m_lGroups[g]->m_lLayers.size(); i++) { //visible - layersbox.HSplitTop(12.0f, &slot, &layersbox); - slot.VSplitLeft(12.0f, 0, &button); - button.VSplitLeft(15, &visible_toggle, &button); + LayersBox.HSplitTop(12.0f, &Slot, &LayersBox); + Slot.VSplitLeft(12.0f, 0, &Button); + Button.VSplitLeft(15, &VisibleToggle, &Button); - if(DoButton_ButtonL(&map.groups[g]->layers[i]->visible, map.groups[g]->layers[i]->visible?"V":"H", 0, &visible_toggle, 0, "Toggle layer visibility")) - map.groups[g]->layers[i]->visible = !map.groups[g]->layers[i]->visible; + if(DoButton_Ex(&m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible, m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle layer visibility", CUI::CORNER_L)) + m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible = !m_Map.m_lGroups[g]->m_lLayers[i]->m_Visible; - sprintf(buf, "#%d %s ", i, map.groups[g]->layers[i]->type_name); - if(int result = DoButton_ButtonR(map.groups[g]->layers[i], buf, g==selected_group&&i==selected_layer, &button, - BUTTON_CONTEXT, "Select layer. Right click for properties.")) + str_format(aBuf, sizeof(aBuf),"#%d %s ", i, m_Map.m_lGroups[g]->m_lLayers[i]->m_pTypeName); + if(int Result = DoButton_Ex(m_Map.m_lGroups[g]->m_lLayers[i], aBuf, g==m_SelectedGroup&&i==m_SelectedLayer, &Button, + BUTTON_CONTEXT, "Select layer. Right click for properties.", CUI::CORNER_R)) { - selected_layer = i; - selected_group = g; - static int layer_popup_id = 0; - if(result == 2) - ui_invoke_popup_menu(&layer_popup_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, popup_layer); + m_SelectedLayer = i; + m_SelectedGroup = g; + static int s_LayerPopupId = 0; + if(Result == 2) + UiInvokePopupMenu(&s_LayerPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupLayer); } - - - layersbox.HSplitTop(2.0f, &slot, &layersbox); + + + LayersBox.HSplitTop(2.0f, &Slot, &LayersBox); } - layersbox.HSplitTop(5.0f, &slot, &layersbox); + LayersBox.HSplitTop(5.0f, &Slot, &LayersBox); } } - + { - layersbox.HSplitTop(12.0f, &slot, &layersbox); + LayersBox.HSplitTop(12.0f, &Slot, &LayersBox); - static int new_group_button = 0; - if(DoButton_Editor(&new_group_button, "Add Group", 0, &slot, 0, "Adds a new group")) + static int s_NewGroupButton = 0; + if(DoButton_Editor(&s_NewGroupButton, "Add Group", 0, &Slot, 0, "Adds a new group")) { - map.new_group(); - selected_group = map.groups.len()-1; + m_Map.NewGroup(); + m_SelectedGroup = m_Map.m_lGroups.size()-1; } } - layersbox.HSplitTop(5.0f, &slot, &layersbox); - + LayersBox.HSplitTop(5.0f, &Slot, &LayersBox); + } -static void extract_name(const char *filename, char *name) +static void ExtractName(const char *pFileName, char *pName) { - int len = strlen(filename); - int start = len; - int end = len; - - while(start > 0) + int Len = str_length(pFileName); + int Start = Len; + int End = Len; + + while(Start > 0) { - start--; - if(filename[start] == '/' || filename[start] == '\\') + Start--; + if(pFileName[Start] == '/' || pFileName[Start] == '\\') { - start++; + Start++; break; } } - - end = start; - for(int i = start; i < len; i++) + + End = Start; + for(int i = Start; i < Len; i++) { - if(filename[i] == '.') - end = i; + if(pFileName[i] == '.') + End = i; } - - if(end == start) - end = len; - - int final_len = end-start; - mem_copy(name, &filename[start], final_len); - name[final_len] = 0; - dbg_msg("", "%s %s %d %d", filename, name, start, end); + + if(End == Start) + End = Len; + + int FinalLen = End-Start; + mem_copy(pName, &pFileName[Start], FinalLen); + pName[FinalLen] = 0; + dbg_msg("", "%s %s %d %d", pFileName, pName, Start, End); } -void EDITOR::replace_image(const char *filename, void *user) +void CEditor::ReplaceImage(const char *pFileName, void *pUser) { - EDITOR *editor = (EDITOR *)user; - EDITOR_IMAGE imginfo(editor); - if(!editor->Graphics()->LoadPNG(&imginfo, filename)) + CEditor *pEditor = (CEditor *)pUser; + CEditorImage ImgInfo(pEditor); + if(!pEditor->Graphics()->LoadPNG(&ImgInfo, pFileName)) return; - - EDITOR_IMAGE *img = editor->map.images[editor->selected_image]; - editor->Graphics()->UnloadTexture(img->tex_id); - *img = imginfo; - extract_name(filename, img->name); - img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0); + + CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage]; + pEditor->Graphics()->UnloadTexture(pImg->m_TexId); + *pImg = ImgInfo; + ExtractName(pFileName, pImg->m_aName); + pImg->m_TexId = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); } -void EDITOR::add_image(const char *filename, void *user) +void CEditor::AddImage(const char *pFileName, void *pUser) { - EDITOR *editor = (EDITOR *)user; - EDITOR_IMAGE imginfo(editor); - if(!editor->Graphics()->LoadPNG(&imginfo, filename)) + CEditor *pEditor = (CEditor *)pUser; + CEditorImage ImgInfo(pEditor); + if(!pEditor->Graphics()->LoadPNG(&ImgInfo, pFileName)) return; - EDITOR_IMAGE *img = new EDITOR_IMAGE(editor); - *img = imginfo; - img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0); - img->external = 1; // external by default - extract_name(filename, img->name); - editor->map.images.add(img); + CEditorImage *pImg = new CEditorImage(pEditor); + *pImg = ImgInfo; + pImg->m_TexId = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); + pImg->m_External = 1; // external by default + ExtractName(pFileName, pImg->m_aName); + + for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i) + { + if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName)) + return; + } + + pEditor->m_Map.m_lImages.add(pImg); } -static int modify_index_deleted_index; -static void modify_index_deleted(int *index) +static int gs_ModifyIndexDeletedIndex; +static void ModifyIndexDeleted(int *pIndex) { - if(*index == modify_index_deleted_index) - *index = -1; - else if(*index > modify_index_deleted_index) - *index = *index - 1; + if(*pIndex == gs_ModifyIndexDeletedIndex) + *pIndex = -1; + else if(*pIndex > gs_ModifyIndexDeletedIndex) + *pIndex = *pIndex - 1; } -int EDITOR::popup_image(EDITOR *pEditor, CUIRect view) +int CEditor::PopupImage(CEditor *pEditor, CUIRect View) { - static int replace_button = 0; - static int remove_button = 0; + static int s_ReplaceButton = 0; + static int s_RemoveButton = 0; - CUIRect slot; - view.HSplitTop(2.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - EDITOR_IMAGE *img = pEditor->map.images[pEditor->selected_image]; - - static int external_button = 0; - if(img->external) + CUIRect Slot; + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage]; + + static int s_ExternalButton = 0; + if(pImg->m_External) { - if(pEditor->DoButton_MenuItem(&external_button, "Embedd", 0, &slot, 0, "Embedds the image into the map file.")) + if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Embedd", 0, &Slot, 0, "Embedds the image into the map file.")) { - img->external = 0; + pImg->m_External = 0; return 1; } } else - { - if(pEditor->DoButton_MenuItem(&external_button, "Make external", 0, &slot, 0, "Removes the image from the map file.")) + { + if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file.")) { - img->external = 1; + pImg->m_External = 1; return 1; } } - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&replace_button, "Replace", 0, &slot, 0, "Replaces the image with a new one")) + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one")) { - pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Replace Image", "Replace", "mapres/", "", replace_image, pEditor); + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Replace Image", "Replace", "mapres/", "", ReplaceImage, pEditor); return 1; } - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&remove_button, "Remove", 0, &slot, 0, "Removes the image from the map")) + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_RemoveButton, "Remove", 0, &Slot, 0, "Removes the image from the map")) { - delete img; - pEditor->map.images.removebyindex(pEditor->selected_image); - modify_index_deleted_index = pEditor->selected_image; - pEditor->map.modify_image_index(modify_index_deleted); + delete pImg; + pEditor->m_Map.m_lImages.remove_index(pEditor->m_SelectedImage); + gs_ModifyIndexDeletedIndex = pEditor->m_SelectedImage; + pEditor->m_Map.ModifyImageIndex(ModifyIndexDeleted); return 1; } @@ -1896,712 +1809,722 @@ int EDITOR::popup_image(EDITOR *pEditor, CUIRect view) } -void EDITOR::render_images(CUIRect toolbox, CUIRect toolbar, CUIRect view) +void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) { for(int e = 0; e < 2; e++) // two passes, first embedded, then external { - CUIRect slot; - toolbox.HSplitTop(15.0f, &slot, &toolbox); + CUIRect Slot; + ToolBox.HSplitTop(15.0f, &Slot, &ToolBox); if(e == 0) - UI()->DoLabel(&slot, "Embedded", 12.0f, 0); + UI()->DoLabel(&Slot, "Embedded", 12.0f, 0); else - UI()->DoLabel(&slot, "External", 12.0f, 0); - - for(int i = 0; i < map.images.len(); i++) + UI()->DoLabel(&Slot, "External", 12.0f, 0); + + for(int i = 0; i < m_Map.m_lImages.size(); i++) { - if((e && !map.images[i]->external) || - (!e && map.images[i]->external)) + if((e && !m_Map.m_lImages[i]->m_External) || + (!e && m_Map.m_lImages[i]->m_External)) { continue; } - - char buf[128]; - sprintf(buf, "%s", map.images[i]->name); - toolbox.HSplitTop(12.0f, &slot, &toolbox); - - if(int result = DoButton_Editor(&map.images[i], buf, selected_image == i, &slot, + + char aBuf[128]; + str_copy(aBuf, m_Map.m_lImages[i]->m_aName, sizeof(aBuf)); + ToolBox.HSplitTop(12.0f, &Slot, &ToolBox); + + if(int Result = DoButton_Editor(&m_Map.m_lImages[i], aBuf, m_SelectedImage == i, &Slot, BUTTON_CONTEXT, "Select image")) { - selected_image = i; - - static int popup_image_id = 0; - if(result == 2) - ui_invoke_popup_menu(&popup_image_id, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, popup_image); + m_SelectedImage = i; + + static int s_PopupImageId = 0; + if(Result == 2) + UiInvokePopupMenu(&s_PopupImageId, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, PopupImage); } - - toolbox.HSplitTop(2.0f, 0, &toolbox); - + + ToolBox.HSplitTop(2.0f, 0, &ToolBox); + // render image - if(selected_image == i) + if(m_SelectedImage == i) { CUIRect r; - view.Margin(10.0f, &r); + View.Margin(10.0f, &r); if(r.h < r.w) r.w = r.h; else r.h = r.w; - Graphics()->TextureSet(map.images[i]->tex_id); + Graphics()->TextureSet(m_Map.m_lImages[i]->m_TexId); Graphics()->BlendNormal(); Graphics()->QuadsBegin(); - Graphics()->QuadsDrawTL(r.x, r.y, r.w, r.h); + IGraphics::CQuadItem QuadItem(r.x, r.y, r.w, r.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + } } } - - CUIRect slot; - toolbox.HSplitTop(5.0f, &slot, &toolbox); - - // new image - static int new_image_button = 0; - toolbox.HSplitTop(10.0f, &slot, &toolbox); - toolbox.HSplitTop(12.0f, &slot, &toolbox); - if(DoButton_Editor(&new_image_button, "Add", 0, &slot, 0, "Load a new image to use in the map")) - invoke_file_dialog(LISTDIRTYPE_ALL, "Add Image", "Add", "mapres/", "", add_image, this); -} + CUIRect Slot; + ToolBox.HSplitTop(5.0f, &Slot, &ToolBox); -static int file_dialog_dirtypes = 0; -static const char *file_dialog_title = 0; -static const char *file_dialog_button_text = 0; -static void (*file_dialog_func)(const char *filename, void *user); -static void *file_dialog_user = 0; -static char file_dialog_filename[512] = {0}; -static char file_dialog_path[512] = {0}; -static char file_dialog_complete_filename[512] = {0}; -static int files_num = 0; -int files_startat = 0; -int files_cur = 0; -int files_stopat = 999; - -struct LISTDIRINFO -{ - CUIRect *rect; - EDITOR *editor; + // new image + static int s_NewImageButton = 0; + ToolBox.HSplitTop(10.0f, &Slot, &ToolBox); + ToolBox.HSplitTop(12.0f, &Slot, &ToolBox); + if(DoButton_Editor(&s_NewImageButton, "Add", 0, &Slot, 0, "Load a new image to use in the map")) + InvokeFileDialog(IStorage::TYPE_ALL, "Add Image", "Add", "mapres/", "", AddImage, this); +} + + +static int gs_FileDialogDirTypes = 0; +static const char *gs_pFileDialogTitle = 0; +static const char *gs_pFileDialogButtonText = 0; +static void (*gs_pfnFileDialogFunc)(const char *pFileName, void *pUser); +static void *gs_pFileDialogUser = 0; +static char gs_FileDialogFileName[512] = {0}; +static char gs_aFileDialogPath[512] = {0}; +static char gs_aFileDialogCompleteFilename[512] = {0}; +static int gs_FilesNum = 0; +int g_FilesStartAt = 0; +int g_FilesCur = 0; +int g_FilesStopAt = 999; + +struct CListDirInfo +{ + CUIRect *m_pRect; + CEditor *m_pEditor; }; -static void editor_listdir_callback(const char *name, int is_dir, void *user) +static void EditorListdirCallback(const char *pName, int IsDir, void *pUser) { - if(name[0] == '.' || is_dir) // skip this shit! + if(pName[0] == '.' || IsDir) // skip this shit! return; - - if(files_cur > files_num) - files_num = files_cur; - - files_cur++; - if(files_cur-1 < files_startat || files_cur > files_stopat) + + if(g_FilesCur > gs_FilesNum) + gs_FilesNum = g_FilesCur; + + g_FilesCur++; + if(g_FilesCur-1 < g_FilesStartAt || g_FilesCur > g_FilesStopAt) return; - - LISTDIRINFO *info = (LISTDIRINFO *)user; - CUIRect *view = info->rect; - CUIRect button; - view->HSplitTop(15.0f, &button, view); - view->HSplitTop(2.0f, 0, view); + + CListDirInfo *pInfo = (CListDirInfo *)pUser; + CUIRect *pView = pInfo->m_pRect; + CUIRect Button; + pView->HSplitTop(15.0f, &Button, pView); + pView->HSplitTop(2.0f, 0, pView); //char buf[512]; - - if(info->editor->DoButton_File((void*)(10+(int)button.y), name, 0, &button, 0, 0)) + + if(pInfo->m_pEditor->DoButton_File((void*)(10+(int)Button.y), pName, 0, &Button, 0, 0)) { - strncpy(file_dialog_filename, name, sizeof(file_dialog_filename)); - - file_dialog_complete_filename[0] = 0; - strcat(file_dialog_complete_filename, file_dialog_path); - strcat(file_dialog_complete_filename, file_dialog_filename); + str_copy(gs_FileDialogFileName, pName, sizeof(gs_FileDialogFileName)); + + gs_aFileDialogCompleteFilename[0] = 0; + str_append(gs_aFileDialogCompleteFilename, gs_aFileDialogPath, sizeof(gs_aFileDialogCompleteFilename)); + str_append(gs_aFileDialogCompleteFilename, gs_FileDialogFileName, sizeof(gs_aFileDialogCompleteFilename)); - if(inp_mouse_doubleclick()) + if(pInfo->m_pEditor->Input()->MouseDoubleClick()) { - if(file_dialog_func) - file_dialog_func(file_dialog_complete_filename, user); - info->editor->dialog = DIALOG_NONE; + if(gs_pfnFileDialogFunc) + gs_pfnFileDialogFunc(gs_aFileDialogCompleteFilename, pInfo->m_pEditor); + pInfo->m_pEditor->m_Dialog = DIALOG_NONE; } } } -void EDITOR::render_file_dialog() +void CEditor::RenderFileDialog() { // GUI coordsys Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); - - CUIRect view = *UI()->Screen(); - RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.25f), 0, 0); - view.VMargin(150.0f, &view); - view.HMargin(50.0f, &view); - RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.75f), CUI::CORNER_ALL, 5.0f); - view.Margin(10.0f, &view); - - CUIRect title, filebox, filebox_label, buttonbar, scroll; - view.HSplitTop(18.0f, &title, &view); - view.HSplitTop(5.0f, 0, &view); // some spacing - view.HSplitBottom(14.0f, &view, &buttonbar); - view.HSplitBottom(10.0f, &view, 0); // some spacing - view.HSplitBottom(14.0f, &view, &filebox); - filebox.VSplitLeft(50.0f, &filebox_label, &filebox); - view.VSplitRight(15.0f, &view, &scroll); - + + CUIRect View = *UI()->Screen(); + RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.25f), 0, 0); + View.VMargin(150.0f, &View); + View.HMargin(50.0f, &View); + RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.75f), CUI::CORNER_ALL, 5.0f); + View.Margin(10.0f, &View); + + CUIRect Title, FileBox, FileBoxLabel, ButtonBar, Scroll; + View.HSplitTop(18.0f, &Title, &View); + View.HSplitTop(5.0f, 0, &View); // some spacing + View.HSplitBottom(14.0f, &View, &ButtonBar); + View.HSplitBottom(10.0f, &View, 0); // some spacing + View.HSplitBottom(14.0f, &View, &FileBox); + FileBox.VSplitLeft(55.0f, &FileBoxLabel, &FileBox); + View.VSplitRight(15.0f, &View, &Scroll); + // title - RenderTools()->DrawUIRect(&title, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 5.0f); - title.VMargin(10.0f, &title); - UI()->DoLabel(&title, file_dialog_title, 14.0f, -1, -1); - + RenderTools()->DrawUIRect(&Title, vec4(1, 1, 1, 0.25f), CUI::CORNER_ALL, 4.0f); + Title.VMargin(10.0f, &Title); + UI()->DoLabel(&Title, gs_pFileDialogTitle, 12.0f, -1, -1); + // filebox - UI()->DoLabel(&filebox_label, "Filename:", 10.0f, -1, -1); - - static int filebox_id = 0; - DoEditBox(&filebox_id, &filebox, file_dialog_filename, sizeof(file_dialog_filename), 10.0f); + static int s_FileBoxId = 0; + UI()->DoLabel(&FileBoxLabel, "Filename:", 10.0f, -1, -1); + DoEditBox(&s_FileBoxId, &FileBox, gs_FileDialogFileName, sizeof(gs_FileDialogFileName), 10.0f); - file_dialog_complete_filename[0] = 0; - strcat(file_dialog_complete_filename, file_dialog_path); - strcat(file_dialog_complete_filename, file_dialog_filename); - - int num = (int)(view.h/17.0); - static float scrollvalue = 0; - static int scrollbar = 0; - scroll.HMargin(5.0f, &scroll); - scrollvalue = ui_do_scrollbar_v(&scrollbar, &scroll, scrollvalue); - - int scrollnum = files_num-num+10; - if(scrollnum > 0) + gs_aFileDialogCompleteFilename[0] = 0; + str_append(gs_aFileDialogCompleteFilename, gs_aFileDialogPath, sizeof(gs_aFileDialogCompleteFilename)); + str_append(gs_aFileDialogCompleteFilename, gs_FileDialogFileName, sizeof(gs_aFileDialogCompleteFilename)); + + int Num = (int)(View.h/17.0); + static float s_ScrollValue = 0; + static int ScrollBar = 0; + Scroll.HMargin(5.0f, &Scroll); + s_ScrollValue = UiDoScrollbarV(&ScrollBar, &Scroll, s_ScrollValue); + + int ScrollNum = gs_FilesNum-Num+10; + if(ScrollNum > 0) { - if(inp_key_presses(KEY_MOUSE_WHEEL_UP)) - scrollvalue -= 3.0f/scrollnum; - if(inp_key_presses(KEY_MOUSE_WHEEL_DOWN)) - scrollvalue += 3.0f/scrollnum; - - if(scrollvalue < 0) scrollvalue = 0; - if(scrollvalue > 1) scrollvalue = 1; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + s_ScrollValue -= 3.0f/ScrollNum; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + s_ScrollValue += 3.0f/ScrollNum; + + if(s_ScrollValue < 0) s_ScrollValue = 0; + if(s_ScrollValue > 1) s_ScrollValue = 1; } else - scrollnum = 0; - - files_startat = (int)(scrollnum*scrollvalue); - if(files_startat < 0) - files_startat = 0; - - files_stopat = files_startat+num; - - files_cur = 0; - + ScrollNum = 0; + + g_FilesStartAt = (int)(ScrollNum*s_ScrollValue); + if(g_FilesStartAt < 0) + g_FilesStartAt = 0; + + g_FilesStopAt = g_FilesStartAt+Num; + + g_FilesCur = 0; + // set clipping - UI()->ClipEnable(&view); - + UI()->ClipEnable(&View); + // the list - LISTDIRINFO info; - info.rect = &view; - info.editor = this; - engine_listdir(file_dialog_dirtypes, file_dialog_path, editor_listdir_callback, &info); - + CListDirInfo Info; + Info.m_pRect = &View; + Info.m_pEditor = this; + + // TODO: lazy ass coding, should store the interface pointer somewere + Kernel()->RequestInterface<IStorage>()->ListDirectory(gs_FileDialogDirTypes, gs_aFileDialogPath, EditorListdirCallback, &Info); + // disable clipping again UI()->ClipDisable(); - + // the buttons - static int ok_button = 0; - static int cancel_button = 0; + static int s_OkButton = 0; + static int s_CancelButton = 0; - CUIRect button; - buttonbar.VSplitRight(50.0f, &buttonbar, &button); - if(DoButton_Editor(&ok_button, file_dialog_button_text, 0, &button, 0, 0) || inp_key_pressed(KEY_RETURN)) + CUIRect Button; + ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button); + if(DoButton_Editor(&s_OkButton, gs_pFileDialogButtonText, 0, &Button, 0, 0) || Input()->KeyPressed(KEY_RETURN)) { - if(file_dialog_func) - file_dialog_func(file_dialog_complete_filename, file_dialog_user); - dialog = DIALOG_NONE; + if(gs_pfnFileDialogFunc) + gs_pfnFileDialogFunc(gs_aFileDialogCompleteFilename, gs_pFileDialogUser); + m_Dialog = DIALOG_NONE; } - buttonbar.VSplitRight(40.0f, &buttonbar, &button); - buttonbar.VSplitRight(50.0f, &buttonbar, &button); - if(DoButton_Editor(&cancel_button, "Cancel", 0, &button, 0, 0) || inp_key_pressed(KEY_ESCAPE)) - dialog = DIALOG_NONE; + ButtonBar.VSplitRight(40.0f, &ButtonBar, &Button); + ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button); + if(DoButton_Editor(&s_CancelButton, "Cancel", 0, &Button, 0, 0) || Input()->KeyPressed(KEY_ESCAPE)) + m_Dialog = DIALOG_NONE; } -void EDITOR::invoke_file_dialog(int listdirtypes, const char *title, const char *button_text, - const char *basepath, const char *default_name, - void (*func)(const char *filename, void *user), void *user) +void CEditor::InvokeFileDialog(int ListDirTypes, const char *pTitle, const char *pButtonText, + const char *pBasePath, const char *pDefaultName, + void (*pfnFunc)(const char *pFileName, void *pUser), void *pUser) { - file_dialog_dirtypes = listdirtypes; - file_dialog_title = title; - file_dialog_button_text = button_text; - file_dialog_func = func; - file_dialog_user = user; - file_dialog_filename[0] = 0; - file_dialog_path[0] = 0; - - if(default_name) - strncpy(file_dialog_filename, default_name, sizeof(file_dialog_filename)); - if(basepath) - strncpy(file_dialog_path, basepath, sizeof(file_dialog_path)); - - dialog = DIALOG_FILE; + gs_FileDialogDirTypes = ListDirTypes; + gs_pFileDialogTitle = pTitle; + gs_pFileDialogButtonText = pButtonText; + gs_pfnFileDialogFunc = pfnFunc; + gs_pFileDialogUser = pUser; + gs_FileDialogFileName[0] = 0; + gs_aFileDialogPath[0] = 0; + + if(pDefaultName) + str_copy(gs_FileDialogFileName, pDefaultName, sizeof(gs_FileDialogFileName)); + if(pBasePath) + str_copy(gs_aFileDialogPath, pBasePath, sizeof(gs_aFileDialogPath)); + + m_Dialog = DIALOG_FILE; } -void EDITOR::render_modebar(CUIRect view) +void CEditor::RenderModebar(CUIRect View) { - CUIRect button; + CUIRect Button; // mode buttons { - view.VSplitLeft(40.0f, &button, &view); - static int tile_button = 0; - if(DoButton_ButtonM(&tile_button, "Layers", mode == MODE_LAYERS, &button, 0, "Switch to edit layers.")) - mode = MODE_LAYERS; - - view.VSplitLeft(40.0f, &button, &view); - static int img_button = 0; - if(DoButton_ButtonR(&img_button, "Images", mode == MODE_IMAGES, &button, 0, "Switch to manage images.")) - mode = MODE_IMAGES; + View.VSplitLeft(65.0f, &Button, &View); + Button.HSplitTop(30.0f, 0, &Button); + static int s_Button = 0; + const char *pButName = m_Mode == MODE_LAYERS ? "Layers" : "Images"; + if(DoButton_Tab(&s_Button, pButName, 0, &Button, 0, "Switch between images and layers managment.")) + { + if(m_Mode == MODE_LAYERS) + m_Mode = MODE_IMAGES; + else + m_Mode = MODE_LAYERS; + } } - view.VSplitLeft(5.0f, 0, &view); - - // spacing - //view.VSplitLeft(10.0f, 0, &view); + View.VSplitLeft(5.0f, 0, &View); } -void EDITOR::render_statusbar(CUIRect view) +void CEditor::RenderStatusbar(CUIRect View) { - CUIRect button; - view.VSplitRight(60.0f, &view, &button); - static int envelope_button = 0; - if(DoButton_Editor(&envelope_button, "Envelopes", show_envelope_editor, &button, 0, "Toggles the envelope editor.")) - show_envelope_editor = (show_envelope_editor+1)%4; - - if(tooltip) + CUIRect Button; + View.VSplitRight(60.0f, &View, &Button); + static int s_EnvelopeButton = 0; + if(DoButton_Editor(&s_EnvelopeButton, "Envelopes", m_ShowEnvelopeEditor, &Button, 0, "Toggles the envelope editor.")) + m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+1)%4; + + if(m_pTooltip) { - if(ui_got_context && ui_got_context == UI()->HotItem()) + if(ms_pUiGotContext && ms_pUiGotContext == UI()->HotItem()) { - char buf[512]; - sprintf(buf, "%s Right click for context menu.", tooltip); - UI()->DoLabel(&view, buf, 10.0f, -1, -1); + char aBuf[512]; + str_format(aBuf, sizeof(aBuf),"%s Right click for context menu.", m_pTooltip); + UI()->DoLabel(&View, aBuf, 10.0f, -1, -1); } else - UI()->DoLabel(&view, tooltip, 10.0f, -1, -1); + UI()->DoLabel(&View, m_pTooltip, 10.0f, -1, -1); } } -void EDITOR::render_envelopeeditor(CUIRect view) +void CEditor::RenderEnvelopeEditor(CUIRect View) { - if(selected_envelope < 0) selected_envelope = 0; - if(selected_envelope >= map.envelopes.len()) selected_envelope--; + if(m_SelectedEnvelope < 0) m_SelectedEnvelope = 0; + if(m_SelectedEnvelope >= m_Map.m_lEnvelopes.size()) m_SelectedEnvelope--; - ENVELOPE *envelope = 0; - if(selected_envelope >= 0 && selected_envelope < map.envelopes.len()) - envelope = map.envelopes[selected_envelope]; + CEnvelope *pEnvelope = 0; + if(m_SelectedEnvelope >= 0 && m_SelectedEnvelope < m_Map.m_lEnvelopes.size()) + pEnvelope = m_Map.m_lEnvelopes[m_SelectedEnvelope]; - bool show_colorbar = false; - if(envelope && envelope->channels == 4) - show_colorbar = true; + bool ShowColorBar = false; + if(pEnvelope && pEnvelope->m_Channels == 4) + ShowColorBar = true; - CUIRect toolbar, curvebar, colorbar; - view.HSplitTop(15.0f, &toolbar, &view); - view.HSplitTop(15.0f, &curvebar, &view); - toolbar.Margin(2.0f, &toolbar); - curvebar.Margin(2.0f, &curvebar); + CUIRect ToolBar, CurveBar, ColorBar; + View.HSplitTop(15.0f, &ToolBar, &View); + View.HSplitTop(15.0f, &CurveBar, &View); + ToolBar.Margin(2.0f, &ToolBar); + CurveBar.Margin(2.0f, &CurveBar); - if(show_colorbar) + if(ShowColorBar) { - view.HSplitTop(20.0f, &colorbar, &view); - colorbar.Margin(2.0f, &colorbar); - render_background(colorbar, checker_texture, 16.0f, 1.0f); + View.HSplitTop(20.0f, &ColorBar, &View); + ColorBar.Margin(2.0f, &ColorBar); + RenderBackground(ColorBar, ms_CheckerTexture, 16.0f, 1.0f); } - render_background(view, checker_texture, 32.0f, 0.1f); + RenderBackground(View, ms_CheckerTexture, 32.0f, 0.1f); // do the toolbar { - CUIRect button; - ENVELOPE *new_env = 0; - - toolbar.VSplitRight(50.0f, &toolbar, &button); - static int new_4d_button = 0; - if(DoButton_Editor(&new_4d_button, "Color+", 0, &button, 0, "Creates a new color envelope")) - new_env = map.new_envelope(4); - - toolbar.VSplitRight(5.0f, &toolbar, &button); - toolbar.VSplitRight(50.0f, &toolbar, &button); - static int new_2d_button = 0; - if(DoButton_Editor(&new_2d_button, "Pos.+", 0, &button, 0, "Creates a new pos envelope")) - new_env = map.new_envelope(3); - - if(new_env) // add the default points + CUIRect Button; + CEnvelope *pNewEnv = 0; + + ToolBar.VSplitRight(50.0f, &ToolBar, &Button); + static int s_New4dButton = 0; + if(DoButton_Editor(&s_New4dButton, "Color+", 0, &Button, 0, "Creates a new color envelope")) + pNewEnv = m_Map.NewEnvelope(4); + + ToolBar.VSplitRight(5.0f, &ToolBar, &Button); + ToolBar.VSplitRight(50.0f, &ToolBar, &Button); + static int s_New2dButton = 0; + if(DoButton_Editor(&s_New2dButton, "Pos.+", 0, &Button, 0, "Creates a new pos envelope")) + pNewEnv = m_Map.NewEnvelope(3); + + if(pNewEnv) // add the default points { - if(new_env->channels == 4) + if(pNewEnv->m_Channels == 4) { - new_env->add_point(0, 1,1,1,1); - new_env->add_point(1000, 1,1,1,1); + pNewEnv->AddPoint(0, 1,1,1,1); + pNewEnv->AddPoint(1000, 1,1,1,1); } else { - new_env->add_point(0, 0); - new_env->add_point(1000, 0); + pNewEnv->AddPoint(0, 0); + pNewEnv->AddPoint(1000, 0); } } - - CUIRect shifter, inc, dec; - toolbar.VSplitLeft(60.0f, &shifter, &toolbar); - shifter.VSplitRight(15.0f, &shifter, &inc); - shifter.VSplitLeft(15.0f, &dec, &shifter); - char buf[512]; - sprintf(buf, "%d/%d", selected_envelope+1, map.envelopes.len()); - RenderTools()->DrawUIRect(&shifter, vec4(1,1,1,0.5f), 0, 0.0f); - UI()->DoLabel(&shifter, buf, 10.0f, 0, -1); - - static int prev_button = 0; - if(DoButton_ButtonDec(&prev_button, 0, 0, &dec, 0, "Previous Envelope")) - selected_envelope--; - - static int next_button = 0; - if(DoButton_ButtonInc(&next_button, 0, 0, &inc, 0, "Next Envelope")) - selected_envelope++; - - if(envelope) + + CUIRect Shifter, Inc, Dec; + ToolBar.VSplitLeft(60.0f, &Shifter, &ToolBar); + Shifter.VSplitRight(15.0f, &Shifter, &Inc); + Shifter.VSplitLeft(15.0f, &Dec, &Shifter); + char aBuf[512]; + str_format(aBuf, sizeof(aBuf),"%d/%d", m_SelectedEnvelope+1, m_Map.m_lEnvelopes.size()); + RenderTools()->DrawUIRect(&Shifter, vec4(1,1,1,0.5f), 0, 0.0f); + UI()->DoLabel(&Shifter, aBuf, 10.0f, 0, -1); + + static int s_PrevButton = 0; + if(DoButton_ButtonDec(&s_PrevButton, 0, 0, &Dec, 0, "Previous Envelope")) + m_SelectedEnvelope--; + + static int s_NextButton = 0; + if(DoButton_ButtonInc(&s_NextButton, 0, 0, &Inc, 0, "Next Envelope")) + m_SelectedEnvelope++; + + if(pEnvelope) { - toolbar.VSplitLeft(15.0f, &button, &toolbar); - toolbar.VSplitLeft(35.0f, &button, &toolbar); - UI()->DoLabel(&button, "Name:", 10.0f, -1, -1); - - toolbar.VSplitLeft(80.0f, &button, &toolbar); - - static int name_box = 0; - DoEditBox(&name_box, &button, envelope->name, sizeof(envelope->name), 10.0f); + ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); + ToolBar.VSplitLeft(35.0f, &Button, &ToolBar); + UI()->DoLabel(&Button, "Name:", 10.0f, -1, -1); + + ToolBar.VSplitLeft(80.0f, &Button, &ToolBar); + + static int s_NameBox = 0; + DoEditBox(&s_NameBox, &Button, pEnvelope->m_aName, sizeof(pEnvelope->m_aName), 10.0f); } } - - if(envelope) + + if(pEnvelope) { - static array<int> selection; - static int envelope_editor_id = 0; - static int active_channels = 0xf; - - if(envelope) + static array<int> Selection; + static int sEnvelopeEditorId = 0; + static int s_ActiveChannels = 0xf; + + if(pEnvelope) { - CUIRect button; - - toolbar.VSplitLeft(15.0f, &button, &toolbar); + CUIRect Button; + + ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); - static const char *names[4][4] = { + static const char *s_paNames[4][4] = { {"X", "", "", ""}, {"X", "Y", "", ""}, {"X", "Y", "R", ""}, {"R", "G", "B", "A"}, }; - - static int channel_buttons[4] = {0}; - int bit = 1; - /*ui_draw_button_func draw_func;*/ - - for(int i = 0; i < envelope->channels; i++, bit<<=1) + + static int s_aChannelButtons[4] = {0}; + int Bit = 1; + //ui_draw_button_func draw_func; + + for(int i = 0; i < pEnvelope->m_Channels; i++, Bit<<=1) { - toolbar.VSplitLeft(15.0f, &button, &toolbar); - + ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); + /*if(i == 0) draw_func = draw_editor_button_l; else if(i == envelope->channels-1) draw_func = draw_editor_button_r; else draw_func = draw_editor_button_m;*/ - - if(DoButton_Editor(&channel_buttons[i], names[envelope->channels-1][i], active_channels&bit, &button, 0, 0)) - active_channels ^= bit; + + if(DoButton_Editor(&s_aChannelButtons[i], s_paNames[pEnvelope->m_Channels-1][i], s_ActiveChannels&Bit, &Button, 0, 0)) + s_ActiveChannels ^= Bit; } - } - - float end_time = envelope->end_time(); - if(end_time < 1) - end_time = 1; - - envelope->find_top_bottom(active_channels); - float top = envelope->top; - float bottom = envelope->bottom; - - if(top < 1) - top = 1; - if(bottom >= 0) - bottom = 0; - - float timescale = end_time/view.w; - float valuescale = (top-bottom)/view.h; - - if(UI()->MouseInside(&view)) - UI()->SetHotItem(&envelope_editor_id); - - if(UI()->HotItem() == &envelope_editor_id) + } + + float EndTime = pEnvelope->EndTime(); + if(EndTime < 1) + EndTime = 1; + + pEnvelope->FindTopBottom(s_ActiveChannels); + float Top = pEnvelope->m_Top; + float Bottom = pEnvelope->m_Bottom; + + if(Top < 1) + Top = 1; + if(Bottom >= 0) + Bottom = 0; + + float TimeScale = EndTime/View.w; + float ValueScale = (Top-Bottom)/View.h; + + if(UI()->MouseInside(&View)) + UI()->SetHotItem(&sEnvelopeEditorId); + + if(UI()->HotItem() == &sEnvelopeEditorId) { // do stuff - if(envelope) + if(pEnvelope) { if(UI()->MouseButtonClicked(1)) { // add point - int time = (int)(((UI()->MouseX()-view.x)*timescale)*1000.0f); - //float env_y = (UI()->MouseY()-view.y)/timescale; - float channels[4]; - envelope->eval(time, channels); - envelope->add_point(time, - f2fx(channels[0]), f2fx(channels[1]), - f2fx(channels[2]), f2fx(channels[3])); + int Time = (int)(((UI()->MouseX()-View.x)*TimeScale)*1000.0f); + //float env_y = (UI()->MouseY()-view.y)/TimeScale; + float aChannels[4]; + pEnvelope->Eval(Time, aChannels); + pEnvelope->AddPoint(Time, + f2fx(aChannels[0]), f2fx(aChannels[1]), + f2fx(aChannels[2]), f2fx(aChannels[3])); } - - tooltip = "Press right mouse button to create a new point"; + + m_pTooltip = "Press right mouse button to create a new point"; } } - vec3 colors[] = {vec3(1,0.2f,0.2f), vec3(0.2f,1,0.2f), vec3(0.2f,0.2f,1), vec3(1,1,0.2f)}; + vec3 aColors[] = {vec3(1,0.2f,0.2f), vec3(0.2f,1,0.2f), vec3(0.2f,0.2f,1), vec3(1,1,0.2f)}; // render lines { - UI()->ClipEnable(&view); + UI()->ClipEnable(&View); Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - for(int c = 0; c < envelope->channels; c++) + for(int c = 0; c < pEnvelope->m_Channels; c++) { - if(active_channels&(1<<c)) - Graphics()->SetColor(colors[c].r,colors[c].g,colors[c].b,1); + if(s_ActiveChannels&(1<<c)) + Graphics()->SetColor(aColors[c].r,aColors[c].g,aColors[c].b,1); else - Graphics()->SetColor(colors[c].r*0.5f,colors[c].g*0.5f,colors[c].b*0.5f,1); - - float prev_x = 0; - float results[4]; - envelope->eval(0.000001f, results); - float prev_value = results[c]; - - int steps = (int)((view.w/UI()->Screen()->w) * Graphics()->ScreenWidth()); - for(int i = 1; i <= steps; i++) + Graphics()->SetColor(aColors[c].r*0.5f,aColors[c].g*0.5f,aColors[c].b*0.5f,1); + + float PrevX = 0; + float aResults[4]; + pEnvelope->Eval(0.000001f, aResults); + float PrevValue = aResults[c]; + + int Steps = (int)((View.w/UI()->Screen()->w) * Graphics()->ScreenWidth()); + for(int i = 1; i <= Steps; i++) { - float a = i/(float)steps; - envelope->eval(a*end_time, results); - float v = results[c]; - v = (v-bottom)/(top-bottom); - - Graphics()->LinesDraw(view.x + prev_x*view.w, view.y+view.h - prev_value*view.h, view.x + a*view.w, view.y+view.h - v*view.h); - prev_x = a; - prev_value = v; + float a = i/(float)Steps; + pEnvelope->Eval(a*EndTime, aResults); + float v = aResults[c]; + v = (v-Bottom)/(Top-Bottom); + + IGraphics::CLineItem LineItem(View.x + PrevX*View.w, View.y+View.h - PrevValue*View.h, View.x + a*View.w, View.y+View.h - v*View.h); + Graphics()->LinesDraw(&LineItem, 1); + PrevX = a; + PrevValue = v; } } Graphics()->LinesEnd(); UI()->ClipDisable(); } - + // render curve options { - for(int i = 0; i < envelope->points.len()-1; i++) + for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++) { - float t0 = envelope->points[i].time/1000.0f/end_time; - float t1 = envelope->points[i+1].time/1000.0f/end_time; + float t0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime; + float t1 = pEnvelope->m_lPoints[i+1].m_Time/1000.0f/EndTime; //dbg_msg("", "%f", end_time); - + CUIRect v; - v.x = curvebar.x + (t0+(t1-t0)*0.5f) * curvebar.w; - v.y = curvebar.y; - v.h = curvebar.h; - v.w = curvebar.h; + v.x = CurveBar.x + (t0+(t1-t0)*0.5f) * CurveBar.w; + v.y = CurveBar.y; + v.h = CurveBar.h; + v.w = CurveBar.h; v.x -= v.w/2; - void *id = &envelope->points[i].curvetype; - const char *type_name[] = { + void *pId = &pEnvelope->m_lPoints[i].m_Curvetype; + const char *paTypeName[] = { "N", "L", "S", "F", "M" }; - - if(DoButton_Editor(id, type_name[envelope->points[i].curvetype], 0, &v, 0, "Switch curve type")) - envelope->points[i].curvetype = (envelope->points[i].curvetype+1)%NUM_CURVETYPES; + + if(DoButton_Editor(pId, paTypeName[pEnvelope->m_lPoints[i].m_Curvetype], 0, &v, 0, "Switch curve type")) + pEnvelope->m_lPoints[i].m_Curvetype = (pEnvelope->m_lPoints[i].m_Curvetype+1)%NUM_CURVETYPES; } } - + // render colorbar - if(show_colorbar) + if(ShowColorBar) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - for(int i = 0; i < envelope->points.len()-1; i++) + for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++) { - float r0 = fx2f(envelope->points[i].values[0]); - float g0 = fx2f(envelope->points[i].values[1]); - float b0 = fx2f(envelope->points[i].values[2]); - float a0 = fx2f(envelope->points[i].values[3]); - float r1 = fx2f(envelope->points[i+1].values[0]); - float g1 = fx2f(envelope->points[i+1].values[1]); - float b1 = fx2f(envelope->points[i+1].values[2]); - float a1 = fx2f(envelope->points[i+1].values[3]); - - Graphics()->SetColorVertex(0, r0, g0, b0, a0); - Graphics()->SetColorVertex(1, r1, g1, b1, a1); - Graphics()->SetColorVertex(2, r1, g1, b1, a1); - Graphics()->SetColorVertex(3, r0, g0, b0, a0); - - float x0 = envelope->points[i].time/1000.0f/end_time; + float r0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]); + float g0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]); + float b0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[2]); + float a0 = fx2f(pEnvelope->m_lPoints[i].m_aValues[3]); + float r1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[0]); + float g1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[1]); + float b1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[2]); + float a1 = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[3]); + + IGraphics::CColorVertex Array[4] = {IGraphics::CColorVertex(0, r0, g0, b0, a0), + IGraphics::CColorVertex(1, r1, g1, b1, a1), + IGraphics::CColorVertex(2, r1, g1, b1, a1), + IGraphics::CColorVertex(3, r0, g0, b0, a0)}; + Graphics()->SetColorVertex(Array, 4); + + float x0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime; // float y0 = (fx2f(envelope->points[i].values[c])-bottom)/(top-bottom); - float x1 = envelope->points[i+1].time/1000.0f/end_time; + float x1 = pEnvelope->m_lPoints[i+1].m_Time/1000.0f/EndTime; //float y1 = (fx2f(envelope->points[i+1].values[c])-bottom)/(top-bottom); CUIRect v; - v.x = colorbar.x + x0*colorbar.w; - v.y = colorbar.y; - v.w = (x1-x0)*colorbar.w; - v.h = colorbar.h; - - Graphics()->QuadsDrawTL(v.x, v.y, v.w, v.h); + v.x = ColorBar.x + x0*ColorBar.w; + v.y = ColorBar.y; + v.w = (x1-x0)*ColorBar.w; + v.h = ColorBar.h; + + IGraphics::CQuadItem QuadItem(v.x, v.y, v.w, v.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); } Graphics()->QuadsEnd(); } - + // render handles { - static bool move = false; - - int current_value = 0, current_time = 0; - + static bool s_Move = false; + + int CurrentValue = 0, CurrentTime = 0; + Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - for(int c = 0; c < envelope->channels; c++) + for(int c = 0; c < pEnvelope->m_Channels; c++) { - if(!(active_channels&(1<<c))) + if(!(s_ActiveChannels&(1<<c))) continue; - - for(int i = 0; i < envelope->points.len(); i++) + + for(int i = 0; i < pEnvelope->m_lPoints.size(); i++) { - float x0 = envelope->points[i].time/1000.0f/end_time; - float y0 = (fx2f(envelope->points[i].values[c])-bottom)/(top-bottom); - CUIRect final; - final.x = view.x + x0*view.w; - final.y = view.y+view.h - y0*view.h; - final.x -= 2.0f; - final.y -= 2.0f; - final.w = 4.0f; - final.h = 4.0f; - - void *id = &envelope->points[i].values[c]; - - if(UI()->MouseInside(&final)) - UI()->SetHotItem(id); - - float colormod = 1.0f; + float x0 = pEnvelope->m_lPoints[i].m_Time/1000.0f/EndTime; + float y0 = (fx2f(pEnvelope->m_lPoints[i].m_aValues[c])-Bottom)/(Top-Bottom); + CUIRect Final; + Final.x = View.x + x0*View.w; + Final.y = View.y+View.h - y0*View.h; + Final.x -= 2.0f; + Final.y -= 2.0f; + Final.w = 4.0f; + Final.h = 4.0f; - if(UI()->ActiveItem() == id) + void *pId = &pEnvelope->m_lPoints[i].m_aValues[c]; + + if(UI()->MouseInside(&Final)) + UI()->SetHotItem(pId); + + float ColorMod = 1.0f; + + if(UI()->ActiveItem() == pId) { if(!UI()->MouseButton(0)) { UI()->SetActiveItem(0); - move = false; + s_Move = false; } else { - envelope->points[i].values[c] -= f2fx(mouse_delta_y*valuescale); - if(inp_key_pressed(KEY_LSHIFT) || inp_key_pressed(KEY_RSHIFT)) + pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*ValueScale); + if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) { if(i != 0) { - envelope->points[i].time += (int)((mouse_delta_x*timescale)*1000.0f); - if(envelope->points[i].time < envelope->points[i-1].time) - envelope->points[i].time = envelope->points[i-1].time + 1; - if(i+1 != envelope->points.len() && envelope->points[i].time > envelope->points[i+1].time) - envelope->points[i].time = envelope->points[i+1].time - 1; + pEnvelope->m_lPoints[i].m_Time += (int)((m_MouseDeltaX*TimeScale)*1000.0f); + if(pEnvelope->m_lPoints[i].m_Time < pEnvelope->m_lPoints[i-1].m_Time) + pEnvelope->m_lPoints[i].m_Time = pEnvelope->m_lPoints[i-1].m_Time + 1; + if(i+1 != pEnvelope->m_lPoints.size() && pEnvelope->m_lPoints[i].m_Time > pEnvelope->m_lPoints[i+1].m_Time) + pEnvelope->m_lPoints[i].m_Time = pEnvelope->m_lPoints[i+1].m_Time - 1; } } } - - colormod = 100.0f; + + ColorMod = 100.0f; Graphics()->SetColor(1,1,1,1); } - else if(UI()->HotItem() == id) + else if(UI()->HotItem() == pId) { if(UI()->MouseButton(0)) { - selection.clear(); - selection.add(i); - UI()->SetActiveItem(id); + Selection.clear(); + Selection.add(i); + UI()->SetActiveItem(pId); } // remove point if(UI()->MouseButtonClicked(1)) - envelope->points.removebyindex(i); - - colormod = 100.0f; + pEnvelope->m_lPoints.remove_index(i); + + ColorMod = 100.0f; Graphics()->SetColor(1,0.75f,0.75f,1); - tooltip = "Left mouse to drag. Hold shift to alter time point aswell. Right click to delete."; + m_pTooltip = "Left mouse to drag. Hold shift to alter time point aswell. Right click to delete."; } - if(UI()->ActiveItem() == id || UI()->HotItem() == id) + if(UI()->ActiveItem() == pId || UI()->HotItem() == pId) { - current_time = envelope->points[i].time; - current_value = envelope->points[i].values[c]; + CurrentTime = pEnvelope->m_lPoints[i].m_Time; + CurrentValue = pEnvelope->m_lPoints[i].m_aValues[c]; } - - Graphics()->SetColor(colors[c].r*colormod, colors[c].g*colormod, colors[c].b*colormod, 1.0f); - Graphics()->QuadsDrawTL(final.x, final.y, final.w, final.h); + + Graphics()->SetColor(aColors[c].r*ColorMod, aColors[c].g*ColorMod, aColors[c].b*ColorMod, 1.0f); + IGraphics::CQuadItem QuadItem(Final.x, Final.y, Final.w, Final.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); } } Graphics()->QuadsEnd(); - char buf[512]; - sprintf(buf, "%.3f %.3f", current_time/1000.0f, fx2f(current_value)); - UI()->DoLabel(&toolbar, buf, 10.0f, 0, -1); + char aBuf[512]; + str_format(aBuf, sizeof(aBuf),"%.3f %.3f", CurrentTime/1000.0f, fx2f(CurrentValue)); + UI()->DoLabel(&ToolBar, aBuf, 10.0f, 0, -1); } } } -int EDITOR::popup_menu_file(EDITOR *pEditor, CUIRect view) +int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) { - static int new_map_button = 0; - static int save_button = 0; - static int save_as_button = 0; - static int open_button = 0; - static int append_button = 0; - static int exit_button = 0; - - CUIRect slot; - view.HSplitTop(2.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&new_map_button, "New", 0, &slot, 0, "Creates a new map")) - { - pEditor->reset(); + static int s_NewMapButton = 0; + static int s_SaveButton = 0; + static int s_SaveAsButton = 0; + static int s_OpenButton = 0; + static int s_AppendButton = 0; + static int s_ExitButton = 0; + + CUIRect Slot; + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_NewMapButton, "New", 0, &Slot, 0, "Creates a new map")) + { + pEditor->Reset(); + pEditor->m_aFileName[0] = 0; return 1; } - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&open_button, "Open", 0, &slot, 0, "Opens a map for editing")) + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_OpenButton, "Open", 0, &Slot, 0, "Opens a map for editing")) { - pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Open Map", "Open", "maps/", "", callback_open_map, pEditor); + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Open Map", "Open", "maps/", "", CallbackOpenMap, pEditor); return 1; } - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&append_button, "Append", 0, &slot, 0, "Opens a map and adds everything from that map to the current one")) + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_AppendButton, "Append", 0, &Slot, 0, "Opens a map and adds everything from that map to the current one")) { - pEditor->invoke_file_dialog(LISTDIRTYPE_ALL, "Append Map", "Append", "maps/", "", callback_append_map, pEditor); + pEditor->InvokeFileDialog(IStorage::TYPE_ALL, "Append Map", "Append", "maps/", "", CallbackAppendMap, pEditor); return 1; } - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&save_button, "Save (NOT IMPL)", 0, &slot, 0, "Saves the current map")) + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_SaveButton, "Save", 0, &Slot, 0, "Saves the current map")) { + if(pEditor->m_aFileName[0]) + pEditor->Save(pEditor->m_aFileName); + else + pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, pEditor); return 1; } - view.HSplitTop(2.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&save_as_button, "Save As", 0, &slot, 0, "Saves the current map under a new name")) + View.HSplitTop(2.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name")) { - pEditor->invoke_file_dialog(LISTDIRTYPE_SAVE, "Save Map", "Save", "maps/", "", callback_save_map, pEditor); + pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, "Save Map", "Save", "maps/", "", CallbackSaveMap, pEditor); return 1; } - - view.HSplitTop(10.0f, &slot, &view); - view.HSplitTop(12.0f, &slot, &view); - if(pEditor->DoButton_MenuItem(&exit_button, "Exit", 0, &slot, 0, "Exits from the editor")) + + View.HSplitTop(10.0f, &Slot, &View); + View.HSplitTop(12.0f, &Slot, &View); + if(pEditor->DoButton_MenuItem(&s_ExitButton, "Exit", 0, &Slot, 0, "Exits from the editor")) { - config.cl_editor = 0; + g_Config.m_ClEditor = 0; return 1; - } - + } + return 0; } -void EDITOR::render_menubar(CUIRect menubar) +void CEditor::RenderMenubar(CUIRect MenuBar) { - static CUIRect file /*, view, help*/; + static CUIRect s_File /*, view, help*/; + + MenuBar.VSplitLeft(60.0f, &s_File, &MenuBar); + if(DoButton_Menu(&s_File, "File", 0, &s_File, 0, 0)) + UiInvokePopupMenu(&s_File, 1, s_File.x, s_File.y+s_File.h-1.0f, 120, 150, PopupMenuFile, this); - menubar.VSplitLeft(60.0f, &file, &menubar); - if(DoButton_Menu(&file, "File", 0, &file, 0, 0)) - ui_invoke_popup_menu(&file, 1, file.x, file.y+file.h-1.0f, 120, 150, popup_menu_file, this); - /* menubar.VSplitLeft(5.0f, 0, &menubar); menubar.VSplitLeft(60.0f, &view, &menubar); @@ -2615,288 +2538,320 @@ void EDITOR::render_menubar(CUIRect menubar) */ } -void EDITOR::render() +void CEditor::Render() { // basic start - Graphics()->Clear(1.0f,0.0f,1.0f); - CUIRect view = *UI()->Screen(); + Graphics()->Clear(1.0f, 0.0f, 1.0f); + CUIRect View = *UI()->Screen(); Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); - + // reset tip - tooltip = 0; - + m_pTooltip = 0; + // render checker - render_background(view, checker_texture, 32.0f, 1.0f); - - CUIRect menubar, modebar, toolbar, statusbar, envelope_editor, toolbox; - - if(gui_active) + RenderBackground(View, ms_CheckerTexture, 32.0f, 1.0f); + + CUIRect MenuBar, CModeBar, ToolBar, StatusBar, EnvelopeEditor, ToolBox; + + if(m_GuiActive) { - - view.HSplitTop(16.0f, &menubar, &view); - view.VSplitLeft(80.0f, &toolbox, &view); - view.HSplitTop(16.0f, &toolbar, &view); - view.HSplitBottom(16.0f, &view, &statusbar); - if(show_envelope_editor) + View.HSplitTop(16.0f, &MenuBar, &View); + View.HSplitTop(53.0f, &ToolBar, &View); + View.VSplitLeft(80.0f, &ToolBox, &View); + View.HSplitBottom(16.0f, &View, &StatusBar); + + if(m_ShowEnvelopeEditor) { float size = 125.0f; - if(show_envelope_editor == 2) + if(m_ShowEnvelopeEditor == 2) size *= 2.0f; - else if(show_envelope_editor == 3) + else if(m_ShowEnvelopeEditor == 3) size *= 3.0f; - view.HSplitBottom(size, &view, &envelope_editor); + View.HSplitBottom(size, &View, &EnvelopeEditor); } } - + // a little hack for now - if(mode == MODE_LAYERS) - do_map_editor(view, toolbar); - - if(gui_active) + if(m_Mode == MODE_LAYERS) + DoMapEditor(View, ToolBar); + + if(m_GuiActive) { - float brightness = 0.25f; - render_background(menubar, background_texture, 128.0f, brightness*0); - menubar.Margin(2.0f, &menubar); + float Brightness = 0.25f; + RenderBackground(MenuBar, ms_BackgroundTexture, 128.0f, Brightness*0); + MenuBar.Margin(2.0f, &MenuBar); - render_background(toolbox, background_texture, 128.0f, brightness); - toolbox.Margin(2.0f, &toolbox); - - render_background(toolbar, background_texture, 128.0f, brightness); - toolbar.Margin(2.0f, &toolbar); - toolbar.VSplitLeft(150.0f, &modebar, &toolbar); + RenderBackground(ToolBox, ms_BackgroundTexture, 128.0f, Brightness); + ToolBox.Margin(2.0f, &ToolBox); + + RenderBackground(ToolBar, ms_BackgroundTexture, 128.0f, Brightness); + ToolBar.Margin(2.0f, &ToolBar); + ToolBar.VSplitLeft(100.0f, &CModeBar, &ToolBar); + + RenderBackground(StatusBar, ms_BackgroundTexture, 128.0f, Brightness); + StatusBar.Margin(2.0f, &StatusBar); - render_background(statusbar, background_texture, 128.0f, brightness); - statusbar.Margin(2.0f, &statusbar); - // do the toolbar - if(mode == MODE_LAYERS) - do_toolbar(toolbar); - - if(show_envelope_editor) + if(m_Mode == MODE_LAYERS) + DoToolbar(ToolBar); + + if(m_ShowEnvelopeEditor) { - render_background(envelope_editor, background_texture, 128.0f, brightness); - envelope_editor.Margin(2.0f, &envelope_editor); + RenderBackground(EnvelopeEditor, ms_BackgroundTexture, 128.0f, Brightness); + EnvelopeEditor.Margin(2.0f, &EnvelopeEditor); } } - - - if(mode == MODE_LAYERS) - render_layers(toolbox, toolbar, view); - else if(mode == MODE_IMAGES) - render_images(toolbox, toolbar, view); + + + if(m_Mode == MODE_LAYERS) + RenderLayers(ToolBox, ToolBar, View); + else if(m_Mode == MODE_IMAGES) + RenderImages(ToolBox, ToolBar, View); Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); - if(gui_active) + if(m_GuiActive) { - render_menubar(menubar); - - render_modebar(modebar); - if(show_envelope_editor) - render_envelopeeditor(envelope_editor); + RenderMenubar(MenuBar); + + RenderModebar(CModeBar); + if(m_ShowEnvelopeEditor) + RenderEnvelopeEditor(EnvelopeEditor); } - if(dialog == DIALOG_FILE) + if(m_Dialog == DIALOG_FILE) { - static int null_ui_target = 0; - UI()->SetHotItem(&null_ui_target); - render_file_dialog(); + static int s_NullUiTarget = 0; + UI()->SetHotItem(&s_NullUiTarget); + RenderFileDialog(); } - - - ui_do_popup_menu(); - if(gui_active) - render_statusbar(statusbar); + + UiDoPopupMenu(); + + if(m_GuiActive) + RenderStatusbar(StatusBar); // - if(config.ed_showkeys) + if(g_Config.m_EdShowkeys) { Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); - TEXT_CURSOR cursor; - gfx_text_set_cursor(&cursor, view.x+10, view.y+view.h-24-10, 24.0f, TEXTFLAG_RENDER); - - int nkeys = 0; + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, View.x+10, View.y+View.h-24-10, 24.0f, TEXTFLAG_RENDER); + + int NKeys = 0; for(int i = 0; i < KEY_LAST; i++) { - if(inp_key_pressed(i)) + if(Input()->KeyPressed(i)) { - if(nkeys) - gfx_text_ex(&cursor, " + ", -1); - gfx_text_ex(&cursor, inp_key_name(i), -1); - nkeys++; + if(NKeys) + TextRender()->TextEx(&Cursor, " + ", -1); + TextRender()->TextEx(&Cursor, Input()->KeyName(i), -1); + NKeys++; } } } - - if(show_mouse_pointer) + + if(m_ShowMousePointer) { // render butt ugly mouse cursor float mx = UI()->MouseX(); float my = UI()->MouseY(); - Graphics()->TextureSet(cursor_texture); + Graphics()->TextureSet(ms_CursorTexture); Graphics()->QuadsBegin(); - if(ui_got_context == UI()->HotItem()) + if(ms_pUiGotContext == UI()->HotItem()) Graphics()->SetColor(1,0,0,1); - Graphics()->QuadsDrawTL(mx,my, 16.0f, 16.0f); + IGraphics::CQuadItem QuadItem(mx,my, 16.0f, 16.0f); + Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } - + } -void EDITOR::reset(bool create_default) +void CEditor::Reset(bool CreateDefault) { - map.clean(); + m_Map.Clean(); // create default layers - if(create_default) - map.create_default(entities_texture); - + if(CreateDefault) + m_Map.CreateDefault(ms_EntitiesTexture); + /* { }*/ - - selected_layer = 0; - selected_group = 0; - selected_quad = -1; - selected_points = 0; - selected_envelope = 0; - selected_image = 0; + + m_SelectedLayer = 0; + m_SelectedGroup = 0; + m_SelectedQuad = -1; + m_SelectedPoints = 0; + m_SelectedEnvelope = 0; + m_SelectedImage = 0; } -void MAP::make_game_layer(LAYER *layer) +void CEditorMap::MakeGameLayer(CLayer *pLayer) { - game_layer = (LAYER_GAME *)layer; - game_layer->tex_id = entities_texture; + m_pGameLayer = (CLayerGame *)pLayer; + m_pGameLayer->m_pEditor = m_pEditor; + m_pGameLayer->m_TexId = m_pEditor->ms_EntitiesTexture; } -void MAP::make_game_group(LAYERGROUP *group) +void CEditorMap::MakeGameGroup(CLayerGroup *pGroup) { - game_group = group; - game_group->game_group = true; - game_group->name = "Game"; + m_pGameGroup = pGroup; + m_pGameGroup->m_GameGroup = true; + m_pGameGroup->m_pName = "Game"; } -void MAP::clean() +void CEditorMap::Clean() { - groups.deleteall(); - envelopes.deleteall(); - images.deleteall(); - - game_layer = 0x0; - game_group = 0x0; + m_lGroups.delete_all(); + m_lEnvelopes.delete_all(); + m_lImages.delete_all(); + + m_pGameLayer = 0x0; + m_pGameGroup = 0x0; } -void MAP::create_default(int entities_texture) +void CEditorMap::CreateDefault(int EntitiesTexture) { - make_game_group(new_group()); - make_game_layer(new LAYER_GAME(50, 50)); - game_group->add_layer(game_layer); + MakeGameGroup(NewGroup()); + MakeGameLayer(new CLayerGame(50, 50)); + m_pGameGroup->AddLayer(m_pGameLayer); } -void EDITOR::Init(class IGraphics *pGraphics) +void CEditor::Init() { - m_pGraphics = pGraphics; - - checker_texture = Graphics()->LoadTexture("editor/checker.png", IMG_AUTO, 0); - background_texture = Graphics()->LoadTexture("editor/background.png", IMG_AUTO, 0); - cursor_texture = Graphics()->LoadTexture("editor/cursor.png", IMG_AUTO, 0); - entities_texture = Graphics()->LoadTexture("editor/entities.png", IMG_AUTO, 0); - - tileset_picker.make_palette(); - tileset_picker.readonly = true; - - reset(); + m_pInput = Kernel()->RequestInterface<IInput>(); + m_pClient = Kernel()->RequestInterface<IClient>(); + m_pGraphics = Kernel()->RequestInterface<IGraphics>(); + m_pTextRender = Kernel()->RequestInterface<ITextRender>(); + m_RenderTools.m_pGraphics = m_pGraphics; + m_RenderTools.m_pUI = &m_UI; + m_UI.SetGraphics(m_pGraphics, m_pTextRender); + m_Map.m_pEditor = this; + + ms_CheckerTexture = Graphics()->LoadTexture("editor/checker.png", CImageInfo::FORMAT_AUTO, 0); + ms_BackgroundTexture = Graphics()->LoadTexture("editor/background.png", CImageInfo::FORMAT_AUTO, 0); + ms_CursorTexture = Graphics()->LoadTexture("editor/cursor.png", CImageInfo::FORMAT_AUTO, 0); + ms_EntitiesTexture = Graphics()->LoadTexture("editor/entities.png", CImageInfo::FORMAT_AUTO, 0); + + m_TilesetPicker.m_pEditor = this; + m_TilesetPicker.MakePalette(); + m_TilesetPicker.m_Readonly = true; + + m_Brush.m_pMap = &m_Map; + + Reset(); } -void EDITOR::UpdateAndRender() +void CEditor::DoMapBorder() { - static int mouse_x = 0; - static int mouse_y = 0; - - if(animate) - animate_time = (time_get()-animate_start)/(float)time_freq(); + CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); + + for(int i = 0; i < pT->m_Width*2; ++i) + pT->m_pTiles[i].m_Index = 1; + + for(int i = 0; i < pT->m_Width*pT->m_Height; ++i) + { + if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3) + pT->m_pTiles[i].m_Index = 1; + } + + for(int i = ((pT->m_Width-2)*pT->m_Height); i < pT->m_Width*pT->m_Height; ++i) + pT->m_pTiles[i].m_Index = 1; +} + +void CEditor::UpdateAndRender() +{ + static int s_MouseX = 0; + static int s_MouseY = 0; + + if(m_Animate) + m_AnimateTime = (time_get()-m_AnimateStart)/(float)time_freq(); else - animate_time = 0; - ui_got_context = 0; + m_AnimateTime = 0; + ms_pUiGotContext = 0; // handle mouse movement - float mx, my, mwx, mwy; + float mx, my, Mwx, Mwy; int rx, ry; { - inp_mouse_relative(&rx, &ry); - mouse_delta_x = rx; - mouse_delta_y = ry; - - if(!lock_mouse) + Input()->MouseRelative(&rx, &ry); + m_MouseDeltaX = rx; + m_MouseDeltaY = ry; + + if(!m_LockMouse) { - mouse_x += rx; - mouse_y += ry; + s_MouseX += rx; + s_MouseY += ry; } - - if(mouse_x < 0) mouse_x = 0; - if(mouse_y < 0) mouse_y = 0; - if(mouse_x > UI()->Screen()->w) mouse_x = (int)UI()->Screen()->w; - if(mouse_y > UI()->Screen()->h) mouse_y = (int)UI()->Screen()->h; + + if(s_MouseX < 0) s_MouseX = 0; + if(s_MouseY < 0) s_MouseY = 0; + if(s_MouseX > UI()->Screen()->w) s_MouseX = (int)UI()->Screen()->w; + if(s_MouseY > UI()->Screen()->h) s_MouseY = (int)UI()->Screen()->h; // update the ui - mx = mouse_x; - my = mouse_y; - mwx = 0; - mwy = 0; - + mx = s_MouseX; + my = s_MouseY; + Mwx = 0; + Mwy = 0; + // fix correct world x and y - LAYERGROUP *g = get_selected_group(); + CLayerGroup *g = GetSelectedGroup(); if(g) { - float points[4]; - g->mapping(points); - - float world_width = points[2]-points[0]; - float world_height = points[3]-points[1]; - - mwx = points[0] + world_width * (mouse_x/UI()->Screen()->w); - mwy = points[1] + world_height * (mouse_y/UI()->Screen()->h); - mouse_delta_wx = mouse_delta_x*(world_width / UI()->Screen()->w); - mouse_delta_wy = mouse_delta_y*(world_height / UI()->Screen()->h); + float aPoints[4]; + g->Mapping(aPoints); + + float WorldWidth = aPoints[2]-aPoints[0]; + float WorldHeight = aPoints[3]-aPoints[1]; + + Mwx = aPoints[0] + WorldWidth * (s_MouseX/UI()->Screen()->w); + Mwy = aPoints[1] + WorldHeight * (s_MouseY/UI()->Screen()->h); + m_MouseDeltaWx = m_MouseDeltaX*(WorldWidth / UI()->Screen()->w); + m_MouseDeltaWy = m_MouseDeltaY*(WorldHeight / UI()->Screen()->h); } - - int buttons = 0; - if(inp_key_pressed(KEY_MOUSE_1)) buttons |= 1; - if(inp_key_pressed(KEY_MOUSE_2)) buttons |= 2; - if(inp_key_pressed(KEY_MOUSE_3)) buttons |= 4; - - UI()->Update(mx,my,mwx,mwy,buttons); + + int Buttons = 0; + if(Input()->KeyPressed(KEY_MOUSE_1)) Buttons |= 1; + if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2; + if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4; + + UI()->Update(mx,my,Mwx,Mwy,Buttons); } - + // toggle gui - if(inp_key_down(KEY_TAB)) - gui_active = !gui_active; + if(Input()->KeyDown(KEY_TAB)) + m_GuiActive = !m_GuiActive; - if(inp_key_down(KEY_F5)) - save("maps/debug_test2.map"); + if(Input()->KeyDown(KEY_F5)) + Save("maps/debug_test2.map"); - if(inp_key_down(KEY_F6)) - load("maps/debug_test2.map"); - - if(inp_key_down(KEY_F8)) - load("maps/debug_test.map"); + if(Input()->KeyDown(KEY_F6)) + Load("maps/debug_test2.map"); - if(inp_key_down(KEY_F10)) - show_mouse_pointer = false; + if(Input()->KeyDown(KEY_F8)) + Load("maps/debug_test.map"); - render(); - - if(inp_key_down(KEY_F10)) + if(Input()->KeyDown(KEY_F7)) + Save("maps/quicksave.map"); + + if(Input()->KeyDown(KEY_F10)) + m_ShowMousePointer = false; + + Render(); + + if(Input()->KeyDown(KEY_F10)) { Graphics()->TakeScreenshot(); - show_mouse_pointer = true; + m_ShowMousePointer = true; } - - inp_clear_events(); + + Input()->ClearEvents(); } -IEditor *CreateEditor() { return new EDITOR; } +IEditor *CreateEditor() { return new CEditor; } diff --git a/src/game/editor/ed_editor.h b/src/game/editor/ed_editor.h new file mode 100644 index 00000000..1730fb0a --- /dev/null +++ b/src/game/editor/ed_editor.h @@ -0,0 +1,615 @@ +#ifndef GAME_EDITOR_ED_EDITOR_H +#define GAME_EDITOR_ED_EDITOR_H + +#include <base/system.h> +#include <base/math.h> +#include <base/tl/array.h> +#include <base/tl/algorithm.h> + +#include <math.h> +#include <game/mapitems.h> +#include <game/client/render.h> + +#include <engine/shared/datafile.h> +#include <engine/shared/config.h> +#include <engine/editor.h> +#include <engine/graphics.h> + +#include <game/client/ui.h> + +typedef void (*INDEX_MODIFY_FUNC)(int *pIndex); + +//CRenderTools m_RenderTools; + +// CEditor SPECIFIC +enum +{ + MODE_LAYERS=0, + MODE_IMAGES, + + DIALOG_NONE=0, + DIALOG_FILE, +}; + +struct CEntity +{ + CPoint m_Position; + int m_Type; +}; + +class CEnvelope +{ +public: + int m_Channels; + array<CEnvPoint> m_lPoints; + char m_aName[32]; + float m_Bottom, m_Top; + + CEnvelope(int Chan) + { + m_Channels = Chan; + m_aName[0] = 0; + m_Bottom = 0; + m_Top = 0; + } + + void Resort() + { + sort(m_lPoints.all()); + FindTopBottom(0xf); + } + + void FindTopBottom(int ChannelMask) + { + m_Top = -1000000000.0f; + m_Bottom = 1000000000.0f; + for(int i = 0; i < m_lPoints.size(); i++) + { + for(int c = 0; c < m_Channels; c++) + { + if(ChannelMask&(1<<c)) + { + float v = fx2f(m_lPoints[i].m_aValues[c]); + if(v > m_Top) m_Top = v; + if(v < m_Bottom) m_Bottom = v; + } + } + } + } + + int Eval(float Time, float *pResult) + { + CRenderTools::RenderEvalEnvelope(m_lPoints.base_ptr(), m_lPoints.size(), m_Channels, Time, pResult); + return m_Channels; + } + + void AddPoint(int Time, int v0, int v1=0, int v2=0, int v3=0) + { + CEnvPoint p; + p.m_Time = Time; + p.m_aValues[0] = v0; + p.m_aValues[1] = v1; + p.m_aValues[2] = v2; + p.m_aValues[3] = v3; + p.m_Curvetype = CURVETYPE_LINEAR; + m_lPoints.add(p); + Resort(); + } + + float EndTime() + { + if(m_lPoints.size()) + return m_lPoints[m_lPoints.size()-1].m_Time*(1.0f/1000.0f); + return 0; + } +}; + + +class CLayer; +class CLayerGroup; +class CEditorMap; + +class CLayer +{ +public: + class CEditor *m_pEditor; + class IGraphics *Graphics(); + class ITextRender *TextRender(); + + CLayer() + { + m_Type = LAYERTYPE_INVALID; + m_pTypeName = "(invalid)"; + m_Visible = true; + m_Readonly = false; + m_Flags = 0; + m_pEditor = 0; + } + + virtual ~CLayer() + { + } + + + virtual void BrushSelecting(CUIRect Rect) {} + virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { return 0; } + virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) {} + virtual void BrushDraw(CLayer *pBrush, float x, float y) {} + virtual void BrushPlace(CLayer *pBrush, float x, float y) {} + virtual void BrushFlipX() {} + virtual void BrushFlipY() {} + virtual void BrushRotate(float Amount) {} + + virtual void Render() {} + virtual int RenderProperties(CUIRect *pToolbox) { return 0; } + + virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) {} + virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {} + + virtual void GetSize(float *w, float *h) { *w = 0; *h = 0;} + + const char *m_pTypeName; + int m_Type; + int m_Flags; + + bool m_Readonly; + bool m_Visible; +}; + +class CLayerGroup +{ +public: + class CEditorMap *m_pMap; + + array<CLayer*> m_lLayers; + + int m_OffsetX; + int m_OffsetY; + + int m_ParallaxX; + int m_ParallaxY; + + int m_UseClipping; + int m_ClipX; + int m_ClipY; + int m_ClipW; + int m_ClipH; + + const char *m_pName; + bool m_GameGroup; + bool m_Visible; + + CLayerGroup(); + ~CLayerGroup(); + + void Convert(CUIRect *pRect); + void Render(); + void MapScreen(); + void Mapping(float *pPoints); + + void GetSize(float *w, float *h); + + void DeleteLayer(int Index); + int SwapLayers(int Index0, int Index1); + + bool IsEmpty() const + { + return m_lLayers.size() == 0; + } + + void Clear() + { + m_lLayers.delete_all(); + } + + void AddLayer(CLayer *l) + { + m_lLayers.add(l); + } + + void ModifyImageIndex(INDEX_MODIFY_FUNC Func) + { + for(int i = 0; i < m_lLayers.size(); i++) + m_lLayers[i]->ModifyImageIndex(Func); + } + + void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) + { + for(int i = 0; i < m_lLayers.size(); i++) + m_lLayers[i]->ModifyEnvelopeIndex(Func); + } +}; + +class CEditorImage : public CImageInfo +{ +public: + CEditor *m_pEditor; + + CEditorImage(CEditor *pEditor) + { + m_pEditor = pEditor; + m_TexId = -1; + m_aName[0] = 0; + m_External = 0; + m_Width = 0; + m_Height = 0; + m_pData = 0; + m_Format = 0; + } + + ~CEditorImage(); + + void AnalyseTileFlags(); + + int m_TexId; + int m_External; + char m_aName[128]; + unsigned char m_aTileFlags[256]; +}; + +class CEditorMap +{ + void MakeGameGroup(CLayerGroup *pGroup); + void MakeGameLayer(CLayer *pLayer); +public: + CEditor *m_pEditor; + + CEditorMap() + { + Clean(); + } + + array<CLayerGroup*> m_lGroups; + array<CEditorImage*> m_lImages; + array<CEnvelope*> m_lEnvelopes; + + class CLayerGame *m_pGameLayer; + CLayerGroup *m_pGameGroup; + + CEnvelope *NewEnvelope(int Channels) + { + CEnvelope *e = new CEnvelope(Channels); + m_lEnvelopes.add(e); + return e; + } + + CLayerGroup *NewGroup() + { + CLayerGroup *g = new CLayerGroup; + g->m_pMap = this; + m_lGroups.add(g); + return g; + } + + int SwapGroups(int Index0, int Index1) + { + if(Index0 < 0 || Index0 >= m_lGroups.size()) return Index0; + if(Index1 < 0 || Index1 >= m_lGroups.size()) return Index0; + if(Index0 == Index1) return Index0; + swap(m_lGroups[Index0], m_lGroups[Index1]); + return Index1; + } + + void DeleteGroup(int Index) + { + if(Index < 0 || Index >= m_lGroups.size()) return; + delete m_lGroups[Index]; + m_lGroups.remove_index(Index); + } + + void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) + { + for(int i = 0; i < m_lGroups.size(); i++) + m_lGroups[i]->ModifyImageIndex(pfnFunc); + } + + void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) + { + for(int i = 0; i < m_lGroups.size(); i++) + m_lGroups[i]->ModifyEnvelopeIndex(pfnFunc); + } + + void Clean(); + void CreateDefault(int EntitiesTexture); + + // io + int Save(class IStorage *pStorage, const char *pFilename); + int Load(class IStorage *pStorage, const char *pFilename); +}; + + +struct CProperty +{ + const char *m_pName; + int m_Value; + int m_Type; + int m_Min; + int m_Max; +}; + +enum +{ + PROPTYPE_NULL=0, + PROPTYPE_BOOL, + PROPTYPE_INT_STEP, + PROPTYPE_INT_SCROLL, + PROPTYPE_COLOR, + PROPTYPE_IMAGE, + PROPTYPE_ENVELOPE, +}; + +typedef struct +{ + int x, y; + int w, h; +} RECTi; + +class CLayerTiles : public CLayer +{ +public: + CLayerTiles(int w, int h); + ~CLayerTiles(); + + void Resize(int NewW, int NewH); + + void MakePalette(); + virtual void Render(); + + int ConvertX(float x) const; + int ConvertY(float y) const; + void Convert(CUIRect Rect, RECTi *pOut); + void Snap(CUIRect *pRect); + void Clamp(RECTi *pRect); + + virtual void BrushSelecting(CUIRect Rect); + virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect); + virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect); + virtual void BrushDraw(CLayer *pBrush, float wx, float wy); + virtual void BrushFlipX(); + virtual void BrushFlipY(); + + virtual int RenderProperties(CUIRect *pToolbox); + + virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc); + virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc); + + void PrepareForSave(); + + void GetSize(float *w, float *h) { *w = m_Width*32.0f; *h = m_Height*32.0f; } + + int m_TexId; + int m_Game; + int m_Image; + int m_Width; + int m_Height; + CTile *m_pTiles; +}; + +class CLayerQuads : public CLayer +{ +public: + CLayerQuads(); + ~CLayerQuads(); + + virtual void Render(); + CQuad *NewQuad(); + + virtual void BrushSelecting(CUIRect Rect); + virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect); + virtual void BrushPlace(CLayer *pBrush, float wx, float wy); + virtual void BrushFlipX(); + virtual void BrushFlipY(); + virtual void BrushRotate(float Amount); + + virtual int RenderProperties(CUIRect *pToolbox); + + virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc); + virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc); + + void GetSize(float *w, float *h); + + int m_Image; + array<CQuad> m_lQuads; +}; + +class CLayerGame : public CLayerTiles +{ +public: + CLayerGame(int w, int h); + ~CLayerGame(); + + virtual int RenderProperties(CUIRect *pToolbox); +}; + +class CEditor : public IEditor +{ + class IInput *m_pInput; + class IClient *m_pClient; + class IGraphics *m_pGraphics; + class ITextRender *m_pTextRender; + CRenderTools m_RenderTools; + CUI m_UI; +public: + class IInput *Input() { return m_pInput; }; + class IClient *Client() { return m_pClient; }; + class IGraphics *Graphics() { return m_pGraphics; }; + class ITextRender *TextRender() { return m_pTextRender; }; + CUI *UI() { return &m_UI; } + CRenderTools *RenderTools() { return &m_RenderTools; } + + CEditor() : m_TilesetPicker(16, 16) + { + m_pInput = 0; + m_pClient = 0; + m_pGraphics = 0; + m_pTextRender = 0; + + m_Mode = MODE_LAYERS; + m_Dialog = 0; + m_pTooltip = 0; + + m_aFileName[0] = 0; + + m_WorldOffsetX = 0; + m_WorldOffsetY = 0; + m_EditorOffsetX = 0.0f; + m_EditorOffsetY = 0.0f; + + m_WorldZoom = 1.0f; + m_ZoomLevel = 200; + m_LockMouse = false; + m_ShowMousePointer = true; + m_MouseDeltaX = 0; + m_MouseDeltaY = 0; + m_MouseDeltaWx = 0; + m_MouseDeltaWy = 0; + + m_GuiActive = true; + m_ProofBorders = false; + + m_ShowDetail = true; + m_Animate = false; + m_AnimateStart = 0; + m_AnimateTime = 0; + m_AnimateSpeed = 1; + + m_ShowEnvelopeEditor = 0; + + ms_CheckerTexture = 0; + ms_BackgroundTexture = 0; + ms_CursorTexture = 0; + ms_EntitiesTexture = 0; + + ms_pUiGotContext = 0; + } + + virtual void Init(); + virtual void UpdateAndRender(); + + void InvokeFileDialog(int ListdirType, const char *pTitle, const char *pButtonText, + const char *pBasepath, const char *pDefaultName, + void (*pfnFunc)(const char *pFilename, void *pUser), void *pUser); + + void Reset(bool CreateDefault=true); + int Save(const char *pFilename); + int Load(const char *pFilename); + int Append(const char *pFilename); + void Render(); + + CQuad *GetSelectedQuad(); + CLayer *GetSelectedLayerType(int Index, int Type); + CLayer *GetSelectedLayer(int Index); + CLayerGroup *GetSelectedGroup(); + + int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIds, int *pNewVal); + + int m_Mode; + int m_Dialog; + const char *m_pTooltip; + + char m_aFileName[512]; + + float m_WorldOffsetX; + float m_WorldOffsetY; + float m_EditorOffsetX; + float m_EditorOffsetY; + float m_WorldZoom; + int m_ZoomLevel; + bool m_LockMouse; + bool m_ShowMousePointer; + bool m_GuiActive; + bool m_ProofBorders; + float m_MouseDeltaX; + float m_MouseDeltaY; + float m_MouseDeltaWx; + float m_MouseDeltaWy; + + bool m_ShowDetail; + bool m_Animate; + int64 m_AnimateStart; + float m_AnimateTime; + float m_AnimateSpeed; + + int m_ShowEnvelopeEditor; + + int m_SelectedLayer; + int m_SelectedGroup; + int m_SelectedQuad; + int m_SelectedPoints; + int m_SelectedEnvelope; + int m_SelectedImage; + + static int ms_CheckerTexture; + static int ms_BackgroundTexture; + static int ms_CursorTexture; + static int ms_EntitiesTexture; + + CLayerGroup m_Brush; + CLayerTiles m_TilesetPicker; + + static const void *ms_pUiGotContext; + + CEditorMap m_Map; + + void DoMapBorder(); + int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + + int DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + int DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners); + int DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + + int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + + int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); + int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags=0, const char *pToolTip=0); + + int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false); + + void RenderBackground(CUIRect View, int Texture, float Size, float Brightness); + + void UiInvokePopupMenu(void *pId, int Flags, float x, float y, float w, float h, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra=0); + void UiDoPopupMenu(); + + int UiDoValueSelector(void *pId, CUIRect *r, const char *pLabel, int Current, int Min, int Max, float Scale); + + static int PopupGroup(CEditor *pEditor, CUIRect View); + static int PopupLayer(CEditor *pEditor, CUIRect View); + static int PopupQuad(CEditor *pEditor, CUIRect View); + static int PopupPoint(CEditor *pEditor, CUIRect View); + static int PopupSelectImage(CEditor *pEditor, CUIRect View); + static int PopupImage(CEditor *pEditor, CUIRect View); + static int PopupMenuFile(CEditor *pEditor, CUIRect View); + + + void PopupSelectImageInvoke(int Current, float x, float y); + int PopupSelectImageResult(); + + vec4 ButtonColorMul(const void *pId); + + void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v); + void DoMapEditor(CUIRect View, CUIRect Toolbar); + void DoToolbar(CUIRect Toolbar); + void DoQuad(CQuad *pQuad, int Index); + float UiDoScrollbarV(const void *id, const CUIRect *pRect, float Current); + vec4 GetButtonColor(const void *id, int Checked); + + static void ReplaceImage(const char *pFilename, void *pUser); + static void AddImage(const char *pFilename, void *pUser); + + void RenderImages(CUIRect Toolbox, CUIRect Toolbar, CUIRect View); + void RenderLayers(CUIRect Toolbox, CUIRect Toolbar, CUIRect View); + void RenderModebar(CUIRect View); + void RenderStatusbar(CUIRect View); + void RenderEnvelopeEditor(CUIRect View); + + void RenderMenubar(CUIRect Menubar); + void RenderFileDialog(); +}; + +// make sure to inline this function +inline class IGraphics *CLayer::Graphics() { return m_pEditor->Graphics(); } +inline class ITextRender *CLayer::TextRender() { return m_pEditor->TextRender(); } + +#endif diff --git a/src/game/editor/ed_editor.hpp b/src/game/editor/ed_editor.hpp deleted file mode 100644 index 98d1d960..00000000 --- a/src/game/editor/ed_editor.hpp +++ /dev/null @@ -1,589 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#include <base/system.h> -#include <base/math.hpp> - -#include <stdlib.h> -#include <math.h> -#include "array.hpp" -#include "../mapitems.hpp" -#include "../client/render.hpp" - -#include <engine/e_client_interface.h> -#include <engine/e_datafile.h> -#include <engine/e_config.h> -#include <engine/client/editor.h> - -#include <game/client/ui.hpp> - -typedef void (*INDEX_MODIFY_FUNC)(int *index); - -//CRenderTools m_RenderTools; - -// EDITOR SPECIFIC -template<typename T> -void swap(T &a, T &b) -{ - T tmp = a; - a = b; - b = tmp; -} - -enum -{ - MODE_LAYERS=0, - MODE_IMAGES, - - DIALOG_NONE=0, - DIALOG_FILE, -}; - -typedef struct -{ - POINT position; - int type; -} ENTITY; - -class ENVELOPE -{ -public: - int channels; - array<ENVPOINT> points; - char name[32]; - float bottom, top; - - ENVELOPE(int chan) - { - channels = chan; - name[0] = 0; - bottom = 0; - top = 0; - } - - static int sort_comp(const void *v0, const void *v1) - { - const ENVPOINT *p0 = (const ENVPOINT *)v0; - const ENVPOINT *p1 = (const ENVPOINT *)v1; - if(p0->time < p1->time) - return -1; - if(p0->time > p1->time) - return 1; - return 0; - } - - void resort() - { - qsort(points.getptr(), points.len(), sizeof(ENVPOINT), sort_comp); - find_top_bottom(0xf); - } - - void find_top_bottom(int channelmask) - { - top = -1000000000.0f; - bottom = 1000000000.0f; - for(int i = 0; i < points.len(); i++) - { - for(int c = 0; c < channels; c++) - { - if(channelmask&(1<<c)) - { - float v = fx2f(points[i].values[c]); - if(v > top) top = v; - if(v < bottom) bottom = v; - } - } - } - } - - int eval(float time, float *result) - { - CRenderTools::render_eval_envelope(points.getptr(), points.len(), channels, time, result); - return channels; - } - - void add_point(int time, int v0, int v1=0, int v2=0, int v3=0) - { - ENVPOINT p; - p.time = time; - p.values[0] = v0; - p.values[1] = v1; - p.values[2] = v2; - p.values[3] = v3; - p.curvetype = CURVETYPE_LINEAR; - points.add(p); - resort(); - } - - float end_time() - { - if(points.len()) - return points[points.len()-1].time*(1.0f/1000.0f); - return 0; - } -}; - - -class LAYER; -class LAYERGROUP; -class MAP; - -class LAYER -{ -public: - class EDITOR *editor; - class IGraphics *Graphics(); - - LAYER() - { - type = LAYERTYPE_INVALID; - type_name = "(invalid)"; - visible = true; - readonly = false; - flags = 0; - editor = 0; - } - - virtual ~LAYER() - { - } - - - virtual void brush_selecting(CUIRect rect) {} - virtual int brush_grab(LAYERGROUP *brush, CUIRect rect) { return 0; } - virtual void brush_draw(LAYER *brush, float x, float y) {} - virtual void brush_place(LAYER *brush, float x, float y) {} - virtual void brush_flip_x() {} - virtual void brush_flip_y() {} - virtual void brush_rotate(float amount) {} - - virtual void render() {} - virtual int render_properties(CUIRect *toolbox) { return 0; } - - virtual void modify_image_index(INDEX_MODIFY_FUNC func) {} - virtual void modify_envelope_index(INDEX_MODIFY_FUNC func) {} - - virtual void get_size(float *w, float *h) { *w = 0; *h = 0;} - - const char *type_name; - int type; - int flags; - - bool readonly; - bool visible; -}; - -class LAYERGROUP -{ -public: - class MAP *m_pMap; - - array<LAYER*> layers; - - int offset_x; - int offset_y; - - int parallax_x; - int parallax_y; - - int use_clipping; - int clip_x; - int clip_y; - int clip_w; - int clip_h; - - const char *name; - bool game_group; - bool visible; - - LAYERGROUP(); - ~LAYERGROUP(); - - void convert(CUIRect *rect); - void render(); - void mapscreen(); - void mapping(float *points); - - bool is_empty() const; - void clear(); - void add_layer(LAYER *l); - - void get_size(float *w, float *h); - - void delete_layer(int index); - int swap_layers(int index0, int index1); - - void modify_image_index(INDEX_MODIFY_FUNC func) - { - for(int i = 0; i < layers.len(); i++) - layers[i]->modify_image_index(func); - } - - void modify_envelope_index(INDEX_MODIFY_FUNC func) - { - for(int i = 0; i < layers.len(); i++) - layers[i]->modify_envelope_index(func); - } -}; - -class EDITOR_IMAGE : public IMAGE_INFO -{ -public: - EDITOR *editor; - - EDITOR_IMAGE(EDITOR *ed) - { - editor = editor; - tex_id = -1; - name[0] = 0; - external = 0; - width = 0; - height = 0; - data = 0; - format = 0; - } - - ~EDITOR_IMAGE(); - - void analyse_tileflags(); - - int tex_id; - int external; - char name[128]; - unsigned char tileflags[256]; -}; - -class MAP -{ - void make_game_group(LAYERGROUP *group); - void make_game_layer(LAYER *layer); -public: - EDITOR *editor; - - MAP() - { - clean(); - } - - array<LAYERGROUP*> groups; - array<EDITOR_IMAGE*> images; - array<ENVELOPE*> envelopes; - - class LAYER_GAME *game_layer; - LAYERGROUP *game_group; - - ENVELOPE *new_envelope(int channels) - { - ENVELOPE *e = new ENVELOPE(channels); - envelopes.add(e); - return e; - } - - LAYERGROUP *new_group() - { - LAYERGROUP *g = new LAYERGROUP; - g->m_pMap = this; - groups.add(g); - return g; - } - - int swap_groups(int index0, int index1) - { - if(index0 < 0 || index0 >= groups.len()) return index0; - if(index1 < 0 || index1 >= groups.len()) return index0; - if(index0 == index1) return index0; - swap(groups[index0], groups[index1]); - return index1; - } - - void delete_group(int index) - { - if(index < 0 || index >= groups.len()) return; - delete groups[index]; - groups.removebyindex(index); - } - - void modify_image_index(INDEX_MODIFY_FUNC func) - { - for(int i = 0; i < groups.len(); i++) - groups[i]->modify_image_index(func); - } - - void modify_envelope_index(INDEX_MODIFY_FUNC func) - { - for(int i = 0; i < groups.len(); i++) - groups[i]->modify_envelope_index(func); - } - - void clean(); - void create_default(int entities_texture); - - // io - int save(const char *filename); - int load(const char *filename); -}; - - -struct PROPERTY -{ - const char *name; - int value; - int type; - int min; - int max; -}; - -enum -{ - PROPTYPE_NULL=0, - PROPTYPE_BOOL, - PROPTYPE_INT_STEP, - PROPTYPE_INT_SCROLL, - PROPTYPE_COLOR, - PROPTYPE_IMAGE, - PROPTYPE_ENVELOPE, -}; - -class EDITOR : public IEditor -{ - class IGraphics *m_pGraphics; - CRenderTools m_RenderTools; - CUI m_UI; -public: - - class IGraphics *Graphics() { return m_pGraphics; }; - CUI *UI() { return &m_UI; } - CRenderTools *RenderTools() { return &m_RenderTools; } - - EDITOR() - { - mode = MODE_LAYERS; - dialog = 0; - tooltip = 0; - - world_offset_x = 0; - world_offset_y = 0; - editor_offset_x = 0.0f; - editor_offset_y = 0.0f; - - world_zoom = 1.0f; - zoom_level = 100; - lock_mouse = false; - show_mouse_pointer = true; - mouse_delta_x = 0; - mouse_delta_y = 0; - mouse_delta_wx = 0; - mouse_delta_wy = 0; - - gui_active = true; - proof_borders = false; - - show_detail = true; - animate = false; - animate_start = 0; - animate_time = 0; - animate_speed = 1; - - show_envelope_editor = 0; - } - - virtual void Init(class IGraphics *pGraphics); - virtual void UpdateAndRender(); - - void invoke_file_dialog(int listdir_type, const char *title, const char *button_text, - const char *basepath, const char *default_name, - void (*func)(const char *filename, void *user), void *user); - - void reset(bool create_default=true); - int save(const char *filename); - int load(const char *filename); - int append(const char *filename); - void render(); - - QUAD *get_selected_quad(); - LAYER *get_selected_layer_type(int index, int type); - LAYER *get_selected_layer(int index); - LAYERGROUP *get_selected_group(); - - int do_properties(CUIRect *toolbox, PROPERTY *props, int *ids, int *new_val); - - int mode; - int dialog; - const char *tooltip; - - float world_offset_x; - float world_offset_y; - float editor_offset_x; - float editor_offset_y; - float world_zoom; - int zoom_level; - bool lock_mouse; - bool show_mouse_pointer; - bool gui_active; - bool proof_borders; - float mouse_delta_x; - float mouse_delta_y; - float mouse_delta_wx; - float mouse_delta_wy; - - bool show_detail; - bool animate; - int64 animate_start; - float animate_time; - float animate_speed; - - int show_envelope_editor; - - int selected_layer; - int selected_group; - int selected_quad; - int selected_points; - int selected_envelope; - int selected_image; - - MAP map; - - int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - - int DoButton_ButtonL(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_ButtonM(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_ButtonR(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - - int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - - int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags=0, const char *pToolTip=0); - - int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false); - //static void draw_editor_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - //static void draw_editor_button_menuitem(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - - void render_background(CUIRect view, int texture, float size, float brightness); - - void ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(EDITOR *pEditor, CUIRect rect), void *extra=0); - void ui_do_popup_menu(); - - int ui_do_value_selector(void *id, CUIRect *r, const char *label, int current, int min, int max, float scale); - - static int popup_group(EDITOR *pEditor, CUIRect view); - static int popup_layer(EDITOR *pEditor, CUIRect view); - static int popup_quad(EDITOR *pEditor, CUIRect view); - static int popup_point(EDITOR *pEditor, CUIRect view); - static int popup_select_image(EDITOR *pEditor, CUIRect view); - static int popup_image(EDITOR *pEditor, CUIRect view); - static int popup_menu_file(EDITOR *pEditor, CUIRect view); - - - void popup_select_image_invoke(int current, float x, float y); - int popup_select_image_result(); - - vec4 button_color_mul(const void *id); - - void do_quad_point(QUAD *q, int quad_index, int v); - void do_map_editor(CUIRect view, CUIRect toolbar); - void do_toolbar(CUIRect toolbar); - void do_quad(QUAD *q, int index); - float ui_do_scrollbar_v(const void *id, const CUIRect *rect, float current); - vec4 get_button_color(const void *id, int checked); - - static void replace_image(const char *filename, void *user); - static void add_image(const char *filename, void *user); - - void render_images(CUIRect toolbox, CUIRect toolbar, CUIRect view); - void render_layers(CUIRect toolbox, CUIRect toolbar, CUIRect view); - void render_modebar(CUIRect view); - void render_statusbar(CUIRect view); - void render_envelopeeditor(CUIRect view); - - void render_menubar(CUIRect menubar); - void render_file_dialog(); -}; - -// make sure to inline this function -inline class IGraphics *LAYER::Graphics() { return editor->Graphics(); } - -//extern EDITOR editor; - -typedef struct -{ - int x, y; - int w, h; -} RECTi; - -class LAYER_TILES : public LAYER -{ -public: - LAYER_TILES(int w, int h); - ~LAYER_TILES(); - - void resize(int new_w, int new_h); - - void make_palette(); - virtual void render(); - - int convert_x(float x) const; - int convert_y(float y) const; - void convert(CUIRect rect, RECTi *out); - void snap(CUIRect *rect); - void clamp(RECTi *rect); - - virtual void brush_selecting(CUIRect rect); - virtual int brush_grab(LAYERGROUP *brush, CUIRect rect); - virtual void brush_draw(LAYER *brush, float wx, float wy); - virtual void brush_flip_x(); - virtual void brush_flip_y(); - - virtual int render_properties(CUIRect *toolbox); - - virtual void modify_image_index(INDEX_MODIFY_FUNC func); - virtual void modify_envelope_index(INDEX_MODIFY_FUNC func); - - void prepare_for_save(); - - void get_size(float *w, float *h) { *w = width*32.0f; *h = height*32.0f; } - - int tex_id; - int game; - int image; - int width; - int height; - TILE *tiles; -}; - -class LAYER_QUADS : public LAYER -{ -public: - LAYER_QUADS(); - ~LAYER_QUADS(); - - virtual void render(); - QUAD *new_quad(); - - virtual void brush_selecting(CUIRect rect); - virtual int brush_grab(LAYERGROUP *brush, CUIRect rect); - virtual void brush_place(LAYER *brush, float wx, float wy); - virtual void brush_flip_x(); - virtual void brush_flip_y(); - virtual void brush_rotate(float amount); - - virtual int render_properties(CUIRect *toolbox); - - virtual void modify_image_index(INDEX_MODIFY_FUNC func); - virtual void modify_envelope_index(INDEX_MODIFY_FUNC func); - - void get_size(float *w, float *h); - - int image; - array<QUAD> quads; -}; - -class LAYER_GAME : public LAYER_TILES -{ -public: - LAYER_GAME(int w, int h); - ~LAYER_GAME(); - - virtual int render_properties(CUIRect *toolbox); -}; diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/ed_io.cpp index b8c025fb..8ca4f704 100644 --- a/src/game/editor/ed_io.cpp +++ b/src/game/editor/ed_io.cpp @@ -1,10 +1,9 @@ -#include <string.h> -#include <stdio.h> -#include <engine/client/graphics.h> -#include "ed_editor.hpp" +#include <engine/graphics.h> +#include <engine/storage.h> +#include "ed_editor.h" template<typename T> -static int make_version(int i, const T &v) +static int MakeVersion(int i, const T &v) { return (i<<16)+sizeof(T); } // backwards compatiblity @@ -93,7 +92,7 @@ void editor_load_old(DATAFILE *df, MAP *map) { mapres_tilemap *tmap = (mapres_tilemap *)datafile_get_item(df, start+t,0,0); - LAYER_TILES *l = new LAYER_TILES(tmap->width, tmap->height); + CLayerTiles *l = new CLayerTiles(tmap->width, tmap->height); if(tmap->main) { @@ -113,7 +112,7 @@ void editor_load_old(DATAFILE *df, MAP *map) // process the data unsigned char *src_data = (unsigned char *)datafile_get_data(df, tmap->data); - TILE *dst_data = l->tiles; + CTile *dst_data = l->tiles; for(int y = 0; y < tmap->height; y++) for(int x = 0; x < tmap->width; x++, dst_data++, src_data+=2) @@ -138,12 +137,12 @@ void editor_load_old(DATAFILE *df, MAP *map) EDITOR_IMAGE *img = new EDITOR_IMAGE; img->width = imgres->width; img->height = imgres->height; - img->format = IMG_RGBA; + img->format = CImageInfo::FORMAT_RGBA; // copy image data img->data = mem_alloc(img->width*img->height*4, 1); mem_copy(img->data, data, img->width*img->height*4); - img->tex_id = Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, IMG_AUTO, 0); + img->tex_id = Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, CImageInfo::FORMAT_AUTO, 0); map->images.add(img); // unload image @@ -153,7 +152,7 @@ void editor_load_old(DATAFILE *df, MAP *map) // load entities { - LAYER_GAME *g = map->game_layer; + CLayerGame *g = map->game_layer; g->resize(game_width, game_height); for(int t = MAPRES_ENTS_START; t < MAPRES_ENTS_END; t++) { @@ -190,190 +189,192 @@ void editor_load_old(DATAFILE *df, MAP *map) } }*/ -int EDITOR::save(const char *filename) +int CEditor::Save(const char *pFilename) { - return map.save(filename); + return m_Map.Save(Kernel()->RequestInterface<IStorage>(), pFilename); } -int MAP::save(const char *filename) +int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) { - dbg_msg("editor", "saving to '%s'...", filename); - DATAFILE_OUT *df = datafile_create(filename); - if(!df) + dbg_msg("editor", "saving to '%s'...", pFileName); + CDataFileWriter df; + if(!df.Open(pStorage, pFileName)) { - dbg_msg("editor", "failed to open file '%s'...", filename); + dbg_msg("editor", "failed to open file '%s'...", pFileName); return 0; } // save version { - MAPITEM_VERSION item; - item.version = 1; - datafile_add_item(df, MAPITEMTYPE_VERSION, 0, sizeof(item), &item); + CMapItemVersion Item; + Item.m_Version = 1; + df.AddItem(MAPITEMTYPE_VERSION, 0, sizeof(Item), &Item); } // save images - for(int i = 0; i < images.len(); i++) + for(int i = 0; i < m_lImages.size(); i++) { - EDITOR_IMAGE *img = images[i]; + CEditorImage *pImg = m_lImages[i]; // analyse the image for when saving (should be done when we load the image) // TODO! - img->analyse_tileflags(); + pImg->AnalyseTileFlags(); - MAPITEM_IMAGE item; - item.version = 1; + CMapItemImage Item; + Item.m_Version = 1; - item.width = img->width; - item.height = img->height; - item.external = img->external; - item.image_name = datafile_add_data(df, strlen(img->name)+1, img->name); - if(img->external) - item.image_data = -1; + Item.m_Width = pImg->m_Width; + Item.m_Height = pImg->m_Height; + Item.m_External = pImg->m_External; + Item.m_ImageName = df.AddData(str_length(pImg->m_aName)+1, pImg->m_aName); + if(pImg->m_External) + Item.m_ImageData = -1; else - item.image_data = datafile_add_data(df, item.width*item.height*4, img->data); - datafile_add_item(df, MAPITEMTYPE_IMAGE, i, sizeof(item), &item); + Item.m_ImageData = df.AddData(Item.m_Width*Item.m_Height*4, pImg->m_pData); + df.AddItem(MAPITEMTYPE_IMAGE, i, sizeof(Item), &Item); } // save layers - int layer_count = 0; - for(int g = 0; g < groups.len(); g++) + int LayerCount = 0; + for(int g = 0; g < m_lGroups.size(); g++) { - LAYERGROUP *group = groups[g]; - MAPITEM_GROUP gitem; - gitem.version = MAPITEM_GROUP::CURRENT_VERSION; + CLayerGroup *pGroup = m_lGroups[g]; + CMapItemGroup GItem; + GItem.m_Version = CMapItemGroup::CURRENT_VERSION; - gitem.parallax_x = group->parallax_x; - gitem.parallax_y = group->parallax_y; - gitem.offset_x = group->offset_x; - gitem.offset_y = group->offset_y; - gitem.use_clipping = group->use_clipping; - gitem.clip_x = group->clip_x; - gitem.clip_y = group->clip_y; - gitem.clip_w = group->clip_w; - gitem.clip_h = group->clip_h; - gitem.start_layer = layer_count; - gitem.num_layers = 0; + GItem.m_ParallaxX = pGroup->m_ParallaxX; + GItem.m_ParallaxY = pGroup->m_ParallaxY; + GItem.m_OffsetX = pGroup->m_OffsetX; + GItem.m_OffsetY = pGroup->m_OffsetY; + GItem.m_UseClipping = pGroup->m_UseClipping; + GItem.m_ClipX = pGroup->m_ClipX; + GItem.m_ClipY = pGroup->m_ClipY; + GItem.m_ClipW = pGroup->m_ClipW; + GItem.m_ClipH = pGroup->m_ClipH; + GItem.m_StartLayer = LayerCount; + GItem.m_NumLayers = 0; - for(int l = 0; l < group->layers.len(); l++) + for(int l = 0; l < pGroup->m_lLayers.size(); l++) { - if(group->layers[l]->type == LAYERTYPE_TILES) + if(pGroup->m_lLayers[l]->m_Type == LAYERTYPE_TILES) { dbg_msg("editor", "saving tiles layer"); - LAYER_TILES *layer = (LAYER_TILES *)group->layers[l]; - layer->prepare_for_save(); + CLayerTiles *pLayer = (CLayerTiles *)pGroup->m_lLayers[l]; + pLayer->PrepareForSave(); - MAPITEM_LAYER_TILEMAP item; - item.version = 2; + CMapItemLayerTilemap Item; + Item.m_Version = 2; - item.layer.flags = layer->flags; - item.layer.type = layer->type; + Item.m_Layer.m_Flags = pLayer->m_Flags; + Item.m_Layer.m_Type = pLayer->m_Type; - item.color.r = 255; // not in use right now - item.color.g = 255; - item.color.b = 255; - item.color.a = 255; - item.color_env = -1; - item.color_env_offset = 0; + Item.m_Color.r = 255; // not in use right now + Item.m_Color.g = 255; + Item.m_Color.b = 255; + Item.m_Color.a = 255; + Item.m_ColorEnv = -1; + Item.m_ColorEnvOffset = 0; - item.width = layer->width; - item.height = layer->height; - item.flags = layer->game; - item.image = layer->image; - item.data = datafile_add_data(df, layer->width*layer->height*sizeof(TILE), layer->tiles); - datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item); + Item.m_Width = pLayer->m_Width; + Item.m_Height = pLayer->m_Height; + Item.m_Flags = pLayer->m_Game; + Item.m_Image = pLayer->m_Image; + Item.m_Data = df.AddData(pLayer->m_Width*pLayer->m_Height*sizeof(CTile), pLayer->m_pTiles); + df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); - gitem.num_layers++; - layer_count++; + GItem.m_NumLayers++; + LayerCount++; } - else if(group->layers[l]->type == LAYERTYPE_QUADS) + else if(pGroup->m_lLayers[l]->m_Type == LAYERTYPE_QUADS) { dbg_msg("editor", "saving quads layer"); - LAYER_QUADS *layer = (LAYER_QUADS *)group->layers[l]; - if(layer->quads.len()) + CLayerQuads *pLayer = (CLayerQuads *)pGroup->m_lLayers[l]; + if(pLayer->m_lQuads.size()) { - MAPITEM_LAYER_QUADS item; - item.version = 1; - item.layer.flags = layer->flags; - item.layer.type = layer->type; - item.image = layer->image; + CMapItemLayerQuads Item; + Item.m_Version = 1; + Item.m_Layer.m_Flags = pLayer->m_Flags; + Item.m_Layer.m_Type = pLayer->m_Type; + Item.m_Image = pLayer->m_Image; // add the data - item.num_quads = layer->quads.len(); - item.data = datafile_add_data_swapped(df, layer->quads.len()*sizeof(QUAD), layer->quads.getptr()); - datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item); + Item.m_NumQuads = pLayer->m_lQuads.size(); + Item.m_Data = df.AddDataSwapped(pLayer->m_lQuads.size()*sizeof(CQuad), pLayer->m_lQuads.base_ptr()); + df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); // clean up //mem_free(quads); - gitem.num_layers++; - layer_count++; + GItem.m_NumLayers++; + LayerCount++; } } } - datafile_add_item(df, MAPITEMTYPE_GROUP, g, sizeof(gitem), &gitem); + df.AddItem(MAPITEMTYPE_GROUP, g, sizeof(GItem), &GItem); } // save envelopes - int point_count = 0; - for(int e = 0; e < envelopes.len(); e++) + int PointCount = 0; + for(int e = 0; e < m_lEnvelopes.size(); e++) { - MAPITEM_ENVELOPE item; - item.version = 1; - item.channels = envelopes[e]->channels; - item.start_point = point_count; - item.num_points = envelopes[e]->points.len(); - item.name = -1; + CMapItemEnvelope Item; + Item.m_Version = 1; + Item.m_Channels = m_lEnvelopes[e]->m_Channels; + Item.m_StartPoint = PointCount; + Item.m_NumPoints = m_lEnvelopes[e]->m_lPoints.size(); + Item.m_Name = -1; - datafile_add_item(df, MAPITEMTYPE_ENVELOPE, e, sizeof(item), &item); - point_count += item.num_points; + df.AddItem(MAPITEMTYPE_ENVELOPE, e, sizeof(Item), &Item); + PointCount += Item.m_NumPoints; } // save points - int totalsize = sizeof(ENVPOINT) * point_count; - ENVPOINT *points = (ENVPOINT *)mem_alloc(totalsize, 1); - point_count = 0; + int TotalSize = sizeof(CEnvPoint) * PointCount; + CEnvPoint *pPoints = (CEnvPoint *)mem_alloc(TotalSize, 1); + PointCount = 0; - for(int e = 0; e < envelopes.len(); e++) + for(int e = 0; e < m_lEnvelopes.size(); e++) { - int count = envelopes[e]->points.len(); - mem_copy(&points[point_count], envelopes[e]->points.getptr(), sizeof(ENVPOINT)*count); - point_count += count; + int Count = m_lEnvelopes[e]->m_lPoints.size(); + mem_copy(&pPoints[PointCount], m_lEnvelopes[e]->m_lPoints.base_ptr(), sizeof(CEnvPoint)*Count); + PointCount += Count; } - datafile_add_item(df, MAPITEMTYPE_ENVPOINTS, 0, totalsize, points); + df.AddItem(MAPITEMTYPE_ENVPOINTS, 0, TotalSize, pPoints); // finish the data file - datafile_finish(df); + df.Finish(); dbg_msg("editor", "done"); // send rcon.. if we can - if(client_rcon_authed()) + /* + if(Client()->RconAuthed()) { - client_rcon("sv_map_reload 1"); - } + Client()->Rcon("sv_map_reload 1"); + }*/ return 1; } -int EDITOR::load(const char *filename) +int CEditor::Load(const char *pFileName) { - reset(); - return map.load(filename); + Reset(); + return m_Map.Load(Kernel()->RequestInterface<IStorage>(), pFileName); } -int MAP::load(const char *filename) +int CEditorMap::Load(class IStorage *pStorage, const char *pFileName) { - DATAFILE *df = datafile_load(filename); - if(!df) + CDataFileReader DataFile; + //DATAFILE *df = datafile_load(filename); + if(!DataFile.Open(pStorage, pFileName)) return 0; - clean(); + Clean(); // check version - MAPITEM_VERSION *item = (MAPITEM_VERSION *)datafile_find_item(df, MAPITEMTYPE_VERSION, 0); - if(!item) + CMapItemVersion *pItem = (CMapItemVersion *)DataFile.FindItem(MAPITEMTYPE_VERSION, 0); + if(!pItem) { // import old map /*MAP old_mapstuff; @@ -381,224 +382,231 @@ int MAP::load(const char *filename) editor_load_old(df, this); */ } - else if(item->version == 1) + else if(pItem->m_Version == 1) { //editor.reset(false); // load images { - int start, num; - datafile_get_type(df, MAPITEMTYPE_IMAGE, &start, &num); - for(int i = 0; i < num; i++) + int Start, Num; + DataFile.GetType( MAPITEMTYPE_IMAGE, &Start, &Num); + for(int i = 0; i < Num; i++) { - MAPITEM_IMAGE *item = (MAPITEM_IMAGE *)datafile_get_item(df, start+i, 0, 0); - char *name = (char *)datafile_get_data(df, item->image_name); + CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start+i, 0, 0); + char *pName = (char *)DataFile.GetData(pItem->m_ImageName); // copy base info - EDITOR_IMAGE *img = new EDITOR_IMAGE(editor); - img->external = item->external; + CEditorImage *pImg = new CEditorImage(m_pEditor); + pImg->m_External = pItem->m_External; - if(item->external) + if(pItem->m_External) { - char buf[256]; - sprintf(buf, "mapres/%s.png", name); + char aBuf[256]; + str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName); // load external - EDITOR_IMAGE imginfo(editor); - if(editor->Graphics()->LoadPNG(&imginfo, buf)) + CEditorImage ImgInfo(m_pEditor); + if(m_pEditor->Graphics()->LoadPNG(&ImgInfo, aBuf)) { - *img = imginfo; - img->tex_id = editor->Graphics()->LoadTextureRaw(imginfo.width, imginfo.height, imginfo.format, imginfo.data, IMG_AUTO, 0); - img->external = 1; + *pImg = ImgInfo; + pImg->m_TexId = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); + pImg->m_External = 1; } } else { - img->width = item->width; - img->height = item->height; - img->format = IMG_RGBA; + pImg->m_Width = pItem->m_Width; + pImg->m_Height = pItem->m_Height; + pImg->m_Format = CImageInfo::FORMAT_RGBA; // copy image data - void *data = datafile_get_data(df, item->image_data); - img->data = mem_alloc(img->width*img->height*4, 1); - mem_copy(img->data, data, img->width*img->height*4); - img->tex_id = editor->Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, IMG_AUTO, 0); + void *pData = DataFile.GetData(pItem->m_ImageData); + pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1); + mem_copy(pImg->m_pData, pData, pImg->m_Width*pImg->m_Height*4); + pImg->m_TexId = m_pEditor->Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, pImg->m_Format, pImg->m_pData, CImageInfo::FORMAT_AUTO, 0); } // copy image name - if(name) - strncpy(img->name, name, 128); + if(pName) + str_copy(pImg->m_aName, pName, 128); - images.add(img); + m_lImages.add(pImg); // unload image - datafile_unload_data(df, item->image_data); - datafile_unload_data(df, item->image_name); + DataFile.UnloadData(pItem->m_ImageData); + DataFile.UnloadData(pItem->m_ImageName); } } // load groups { - int layers_start, layers_num; - datafile_get_type(df, MAPITEMTYPE_LAYER, &layers_start, &layers_num); + int LayersStart, LayersNum; + DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); - int start, num; - datafile_get_type(df, MAPITEMTYPE_GROUP, &start, &num); - for(int g = 0; g < num; g++) + int Start, Num; + DataFile.GetType(MAPITEMTYPE_GROUP, &Start, &Num); + for(int g = 0; g < Num; g++) { - MAPITEM_GROUP *gitem = (MAPITEM_GROUP *)datafile_get_item(df, start+g, 0, 0); + CMapItemGroup *pGItem = (CMapItemGroup *)DataFile.GetItem(Start+g, 0, 0); - if(gitem->version < 1 || gitem->version > MAPITEM_GROUP::CURRENT_VERSION) + if(pGItem->m_Version < 1 || pGItem->m_Version > CMapItemGroup::CURRENT_VERSION) continue; - LAYERGROUP *group = new_group(); - group->parallax_x = gitem->parallax_x; - group->parallax_y = gitem->parallax_y; - group->offset_x = gitem->offset_x; - group->offset_y = gitem->offset_y; + CLayerGroup *pGroup = NewGroup(); + pGroup->m_ParallaxX = pGItem->m_ParallaxX; + pGroup->m_ParallaxY = pGItem->m_ParallaxY; + pGroup->m_OffsetX = pGItem->m_OffsetX; + pGroup->m_OffsetY = pGItem->m_OffsetY; - if(gitem->version >= 2) + if(pGItem->m_Version >= 2) { - group->use_clipping = gitem->use_clipping; - group->clip_x = gitem->clip_x; - group->clip_y = gitem->clip_y; - group->clip_w = gitem->clip_w; - group->clip_h = gitem->clip_h; + pGroup->m_UseClipping = pGItem->m_UseClipping; + pGroup->m_ClipX = pGItem->m_ClipX; + pGroup->m_ClipY = pGItem->m_ClipY; + pGroup->m_ClipW = pGItem->m_ClipW; + pGroup->m_ClipH = pGItem->m_ClipH; } - for(int l = 0; l < gitem->num_layers; l++) + for(int l = 0; l < pGItem->m_NumLayers; l++) { - LAYER *layer = 0; - MAPITEM_LAYER *layer_item = (MAPITEM_LAYER *)datafile_get_item(df, layers_start+gitem->start_layer+l, 0, 0); - if(!layer_item) + CLayer *pLayer = 0; + CMapItemLayer *pLayerItem = (CMapItemLayer *)DataFile.GetItem(LayersStart+pGItem->m_StartLayer+l, 0, 0); + if(!pLayerItem) continue; - if(layer_item->type == LAYERTYPE_TILES) + if(pLayerItem->m_Type == LAYERTYPE_TILES) { - MAPITEM_LAYER_TILEMAP *tilemap_item = (MAPITEM_LAYER_TILEMAP *)layer_item; - LAYER_TILES *tiles = 0; + CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem; + CLayerTiles *pTiles = 0; - if(tilemap_item->flags&1) + if(pTilemapItem->m_Flags&1) { - tiles = new LAYER_GAME(tilemap_item->width, tilemap_item->height); - make_game_layer(tiles); - make_game_group(group); + pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height); + MakeGameLayer(pTiles); + MakeGameGroup(pGroup); } else - tiles = new LAYER_TILES(tilemap_item->width, tilemap_item->height); + { + pTiles = new CLayerTiles(pTilemapItem->m_Width, pTilemapItem->m_Height); + pTiles->m_pEditor = m_pEditor; + } - layer = tiles; + pLayer = pTiles; - group->add_layer(tiles); - void *data = datafile_get_data(df, tilemap_item->data); - tiles->image = tilemap_item->image; - tiles->game = tilemap_item->flags&1; + pGroup->AddLayer(pTiles); + void *pData = DataFile.GetData(pTilemapItem->m_Data); + pTiles->m_Image = pTilemapItem->m_Image; + pTiles->m_Game = pTilemapItem->m_Flags&1; - mem_copy(tiles->tiles, data, tiles->width*tiles->height*sizeof(TILE)); + mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); - if(tiles->game && tilemap_item->version == make_version(1, *tilemap_item)) + if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) { - for(int i = 0; i < tiles->width*tiles->height; i++) + for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) { - if(tiles->tiles[i].index) - tiles->tiles[i].index += ENTITY_OFFSET; + if(pTiles->m_pTiles[i].m_Index) + pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET; } } - datafile_unload_data(df, tilemap_item->data); + DataFile.UnloadData(pTilemapItem->m_Data); } - else if(layer_item->type == LAYERTYPE_QUADS) + else if(pLayerItem->m_Type == LAYERTYPE_QUADS) { - MAPITEM_LAYER_QUADS *quads_item = (MAPITEM_LAYER_QUADS *)layer_item; - LAYER_QUADS *quads = new LAYER_QUADS; - layer = quads; - quads->image = quads_item->image; - if(quads->image < -1 || quads->image >= images.len()) - quads->image = -1; - void *data = datafile_get_data_swapped(df, quads_item->data); - group->add_layer(quads); - quads->quads.setsize(quads_item->num_quads); - mem_copy(quads->quads.getptr(), data, sizeof(QUAD)*quads_item->num_quads); - datafile_unload_data(df, quads_item->data); + CMapItemLayerQuads *pQuadsItem = (CMapItemLayerQuads *)pLayerItem; + CLayerQuads *pQuads = new CLayerQuads; + pQuads->m_pEditor = m_pEditor; + pLayer = pQuads; + pQuads->m_Image = pQuadsItem->m_Image; + if(pQuads->m_Image < -1 || pQuads->m_Image >= m_lImages.size()) + pQuads->m_Image = -1; + void *pData = DataFile.GetDataSwapped(pQuadsItem->m_Data); + pGroup->AddLayer(pQuads); + pQuads->m_lQuads.set_size(pQuadsItem->m_NumQuads); + mem_copy(pQuads->m_lQuads.base_ptr(), pData, sizeof(CQuad)*pQuadsItem->m_NumQuads); + DataFile.UnloadData(pQuadsItem->m_Data); } - if(layer) - layer->flags = layer_item->flags; + if(pLayer) + pLayer->m_Flags = pLayerItem->m_Flags; } } } // load envelopes { - ENVPOINT *points = 0; + CEnvPoint *pPoints = 0; { - int start, num; - datafile_get_type(df, MAPITEMTYPE_ENVPOINTS, &start, &num); - if(num) - points = (ENVPOINT *)datafile_get_item(df, start, 0, 0); + int Start, Num; + DataFile.GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num); + if(Num) + pPoints = (CEnvPoint *)DataFile.GetItem(Start, 0, 0); } - int start, num; - datafile_get_type(df, MAPITEMTYPE_ENVELOPE, &start, &num); - for(int e = 0; e < num; e++) + int Start, Num; + DataFile.GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num); + for(int e = 0; e < Num; e++) { - MAPITEM_ENVELOPE *item = (MAPITEM_ENVELOPE *)datafile_get_item(df, start+e, 0, 0); - ENVELOPE *env = new ENVELOPE(item->channels); - env->points.setsize(item->num_points); - mem_copy(env->points.getptr(), &points[item->start_point], sizeof(ENVPOINT)*item->num_points); - envelopes.add(env); + CMapItemEnvelope *pItem = (CMapItemEnvelope *)DataFile.GetItem(Start+e, 0, 0); + CEnvelope *pEnv = new CEnvelope(pItem->m_Channels); + pEnv->m_lPoints.set_size(pItem->m_NumPoints); + mem_copy(pEnv->m_lPoints.base_ptr(), &pPoints[pItem->m_StartPoint], sizeof(CEnvPoint)*pItem->m_NumPoints); + m_lEnvelopes.add(pEnv); } } } - datafile_unload(df); - - return 0; + return 1; } -static int modify_add_amount = 0; -static void modify_add(int *index) +static int gs_ModifyAddAmount = 0; +static void ModifyAdd(int *pIndex) { - if(*index >= 0) - *index += modify_add_amount; + if(*pIndex >= 0) + *pIndex += gs_ModifyAddAmount; } -int EDITOR::append(const char *filename) +int CEditor::Append(const char *pFileName) { - MAP new_map; - int err; - err = new_map.load(filename); - if(err) - return err; + CEditorMap NewMap; + NewMap.m_pEditor = this; + + int Err; + Err = NewMap.Load(Kernel()->RequestInterface<IStorage>(), pFileName); + if(Err) + return Err; // modify indecies - modify_add_amount = map.images.len(); - new_map.modify_image_index(modify_add); + gs_ModifyAddAmount = m_Map.m_lImages.size(); + NewMap.ModifyImageIndex(ModifyAdd); - modify_add_amount = map.envelopes.len(); - new_map.modify_envelope_index(modify_add); + gs_ModifyAddAmount = m_Map.m_lEnvelopes.size(); + NewMap.ModifyEnvelopeIndex(ModifyAdd); // transfer images - for(int i = 0; i < new_map.images.len(); i++) - map.images.add(new_map.images[i]); - new_map.images.clear(); + for(int i = 0; i < NewMap.m_lImages.size(); i++) + m_Map.m_lImages.add(NewMap.m_lImages[i]); + NewMap.m_lImages.clear(); // transfer envelopes - for(int i = 0; i < new_map.envelopes.len(); i++) - map.envelopes.add(new_map.envelopes[i]); - new_map.envelopes.clear(); + for(int i = 0; i < NewMap.m_lEnvelopes.size(); i++) + m_Map.m_lEnvelopes.add(NewMap.m_lEnvelopes[i]); + NewMap.m_lEnvelopes.clear(); // transfer groups - for(int i = 0; i < new_map.groups.len(); i++) + for(int i = 0; i < NewMap.m_lGroups.size(); i++) { - if(new_map.groups[i] == new_map.game_group) - delete new_map.groups[i]; + if(NewMap.m_lGroups[i] == NewMap.m_pGameGroup) + delete NewMap.m_lGroups[i]; else - map.groups.add(new_map.groups[i]); + { + NewMap.m_lGroups[i]->m_pMap = &m_Map; + m_Map.m_lGroups.add(NewMap.m_lGroups[i]); + } } - new_map.groups.clear(); + NewMap.m_lGroups.clear(); // all done \o/ return 0; diff --git a/src/game/editor/ed_layer_game.cpp b/src/game/editor/ed_layer_game.cpp index 9010bc71..82a9cb1d 100644 --- a/src/game/editor/ed_layer_game.cpp +++ b/src/game/editor/ed_layer_game.cpp @@ -1,20 +1,20 @@ -#include "ed_editor.hpp" +#include "ed_editor.h" -LAYER_GAME::LAYER_GAME(int w, int h) -: LAYER_TILES(w, h) +CLayerGame::CLayerGame(int w, int h) +: CLayerTiles(w, h) { - type_name = "Game"; - game = 1; + m_pTypeName = "Game"; + m_Game = 1; } -LAYER_GAME::~LAYER_GAME() +CLayerGame::~CLayerGame() { } -int LAYER_GAME::render_properties(CUIRect *toolbox) +int CLayerGame::RenderProperties(CUIRect *pToolbox) { - int r = LAYER_TILES::render_properties(toolbox); - image = -1; + int r = CLayerTiles::RenderProperties(pToolbox); + m_Image = -1; return r; } diff --git a/src/game/editor/ed_layer_quads.cpp b/src/game/editor/ed_layer_quads.cpp index ce1ba4b6..3aeffc73 100644 --- a/src/game/editor/ed_layer_quads.cpp +++ b/src/game/editor/ed_layer_quads.cpp @@ -1,213 +1,216 @@ -#include <base/math.hpp> +#include <base/math.h> -#include <engine/client/graphics.h> +#include <engine/graphics.h> -#include "ed_editor.hpp" -#include <game/generated/gc_data.hpp> -#include <game/client/render.hpp> +#include "ed_editor.h" +#include <game/generated/client_data.h> +#include <game/client/render.h> -LAYER_QUADS::LAYER_QUADS() +CLayerQuads::CLayerQuads() { - type = LAYERTYPE_QUADS; - type_name = "Quads"; - image = -1; + m_Type = LAYERTYPE_QUADS; + m_pTypeName = "Quads"; + m_Image = -1; } -LAYER_QUADS::~LAYER_QUADS() +CLayerQuads::~CLayerQuads() { } -static void envelope_eval(float time_offset, int env, float *channels, void *user) +static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) { - EDITOR *pEditor = (EDITOR *)user; - if(env < 0 || env > pEditor->map.envelopes.len()) + CEditor *pEditor = (CEditor *)pUser; + if(Env < 0 || Env > pEditor->m_Map.m_lEnvelopes.size()) { - channels[0] = 0; - channels[1] = 0; - channels[2] = 0; - channels[3] = 0; + pChannels[0] = 0; + pChannels[1] = 0; + pChannels[2] = 0; + pChannels[3] = 0; return; } - ENVELOPE *e = pEditor->map.envelopes[env]; - float t = pEditor->animate_time+time_offset; - t *= pEditor->animate_speed; - e->eval(t, channels); + CEnvelope *e = pEditor->m_Map.m_lEnvelopes[Env]; + float t = pEditor->m_AnimateTime+TimeOffset; + t *= pEditor->m_AnimateSpeed; + e->Eval(t, pChannels); } -void LAYER_QUADS::render() +void CLayerQuads::Render() { Graphics()->TextureSet(-1); - if(image >= 0 && image < editor->map.images.len()) - Graphics()->TextureSet(editor->map.images[image]->tex_id); + if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size()) + Graphics()->TextureSet(m_pEditor->m_Map.m_lImages[m_Image]->m_TexId); - editor->RenderTools()->render_quads(quads.getptr(), quads.len(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, envelope_eval, editor); + m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, m_pEditor); } -QUAD *LAYER_QUADS::new_quad() +CQuad *CLayerQuads::NewQuad() { - QUAD *q = &quads[quads.add(QUAD())]; + CQuad *q = &m_lQuads[m_lQuads.add(CQuad())]; - q->pos_env = -1; - q->color_env = -1; - q->pos_env_offset = 0; - q->color_env_offset = 0; + q->m_PosEnv = -1; + q->m_ColorEnv = -1; + q->m_PosEnvOffset = 0; + q->m_ColorEnvOffset = 0; int x = 0, y = 0; - q->points[0].x = x; - q->points[0].y = y; - q->points[1].x = x+64; - q->points[1].y = y; - q->points[2].x = x; - q->points[2].y = y+64; - q->points[3].x = x+64; - q->points[3].y = y+64; - - q->points[4].x = x+32; // pivot - q->points[4].y = y+32; + q->m_aPoints[0].x = x; + q->m_aPoints[0].y = y; + q->m_aPoints[1].x = x+64; + q->m_aPoints[1].y = y; + q->m_aPoints[2].x = x; + q->m_aPoints[2].y = y+64; + q->m_aPoints[3].x = x+64; + q->m_aPoints[3].y = y+64; + + q->m_aPoints[4].x = x+32; // pivot + q->m_aPoints[4].y = y+32; for(int i = 0; i < 5; i++) { - q->points[i].x <<= 10; - q->points[i].y <<= 10; + q->m_aPoints[i].x <<= 10; + q->m_aPoints[i].y <<= 10; } - q->texcoords[0].x = 0; - q->texcoords[0].y = 0; + q->m_aTexcoords[0].x = 0; + q->m_aTexcoords[0].y = 0; - q->texcoords[1].x = 1<<10; - q->texcoords[1].y = 0; + q->m_aTexcoords[1].x = 1<<10; + q->m_aTexcoords[1].y = 0; - q->texcoords[2].x = 0; - q->texcoords[2].y = 1<<10; + q->m_aTexcoords[2].x = 0; + q->m_aTexcoords[2].y = 1<<10; - q->texcoords[3].x = 1<<10; - q->texcoords[3].y = 1<<10; + q->m_aTexcoords[3].x = 1<<10; + q->m_aTexcoords[3].y = 1<<10; - q->colors[0].r = 255; q->colors[0].g = 255; q->colors[0].b = 255; q->colors[0].a = 255; - q->colors[1].r = 255; q->colors[1].g = 255; q->colors[1].b = 255; q->colors[1].a = 255; - q->colors[2].r = 255; q->colors[2].g = 255; q->colors[2].b = 255; q->colors[2].a = 255; - q->colors[3].r = 255; q->colors[3].g = 255; q->colors[3].b = 255; q->colors[3].a = 255; + q->m_aColors[0].r = 255; q->m_aColors[0].g = 255; q->m_aColors[0].b = 255; q->m_aColors[0].a = 255; + q->m_aColors[1].r = 255; q->m_aColors[1].g = 255; q->m_aColors[1].b = 255; q->m_aColors[1].a = 255; + q->m_aColors[2].r = 255; q->m_aColors[2].g = 255; q->m_aColors[2].b = 255; q->m_aColors[2].a = 255; + q->m_aColors[3].r = 255; q->m_aColors[3].g = 255; q->m_aColors[3].b = 255; q->m_aColors[3].a = 255; return q; } -void LAYER_QUADS::brush_selecting(CUIRect rect) +void CLayerQuads::BrushSelecting(CUIRect Rect) { // draw selection rectangle + IGraphics::CLineItem Array[4] = { + IGraphics::CLineItem(Rect.x, Rect.y, Rect.x+Rect.w, Rect.y), + IGraphics::CLineItem(Rect.x+Rect.w, Rect.y, Rect.x+Rect.w, Rect.y+Rect.h), + IGraphics::CLineItem(Rect.x+Rect.w, Rect.y+Rect.h, Rect.x, Rect.y+Rect.h), + IGraphics::CLineItem(Rect.x, Rect.y+Rect.h, Rect.x, Rect.y)}; Graphics()->TextureSet(-1); Graphics()->LinesBegin(); - Graphics()->LinesDraw(rect.x, rect.y, rect.x+rect.w, rect.y); - Graphics()->LinesDraw(rect.x+rect.w, rect.y, rect.x+rect.w, rect.y+rect.h); - Graphics()->LinesDraw(rect.x+rect.w, rect.y+rect.h, rect.x, rect.y+rect.h); - Graphics()->LinesDraw(rect.x, rect.y+rect.h, rect.x, rect.y); + Graphics()->LinesDraw(Array, 4); Graphics()->LinesEnd(); } -int LAYER_QUADS::brush_grab(LAYERGROUP *brush, CUIRect rect) +int CLayerQuads::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { // create new layers - LAYER_QUADS *grabbed = new LAYER_QUADS(); - grabbed->image = image; - brush->add_layer(grabbed); + CLayerQuads *pGrabbed = new CLayerQuads(); + pGrabbed->m_pEditor = m_pEditor; + pGrabbed->m_Image = m_Image; + pBrush->AddLayer(pGrabbed); //dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h); - for(int i = 0; i < quads.len(); i++) + for(int i = 0; i < m_lQuads.size(); i++) { - QUAD *q = &quads[i]; - float px = fx2f(q->points[4].x); - float py = fx2f(q->points[4].y); + CQuad *q = &m_lQuads[i]; + float px = fx2f(q->m_aPoints[4].x); + float py = fx2f(q->m_aPoints[4].y); - if(px > rect.x && px < rect.x+rect.w && py > rect.y && py < rect.y+rect.h) + if(px > Rect.x && px < Rect.x+Rect.w && py > Rect.y && py < Rect.y+Rect.h) { dbg_msg("", "grabbed one"); - QUAD n; + CQuad n; n = *q; for(int p = 0; p < 5; p++) { - n.points[p].x -= f2fx(rect.x); - n.points[p].y -= f2fx(rect.y); + n.m_aPoints[p].x -= f2fx(Rect.x); + n.m_aPoints[p].y -= f2fx(Rect.y); } - grabbed->quads.add(n); + pGrabbed->m_lQuads.add(n); } } - return grabbed->quads.len()?1:0; + return pGrabbed->m_lQuads.size()?1:0; } -void LAYER_QUADS::brush_place(LAYER *brush, float wx, float wy) +void CLayerQuads::BrushPlace(CLayer *pBrush, float wx, float wy) { - LAYER_QUADS *l = (LAYER_QUADS *)brush; - for(int i = 0; i < l->quads.len(); i++) + CLayerQuads *l = (CLayerQuads *)pBrush; + for(int i = 0; i < l->m_lQuads.size(); i++) { - QUAD n = l->quads[i]; + CQuad n = l->m_lQuads[i]; for(int p = 0; p < 5; p++) { - n.points[p].x += f2fx(wx); - n.points[p].y += f2fx(wy); + n.m_aPoints[p].x += f2fx(wx); + n.m_aPoints[p].y += f2fx(wy); } - quads.add(n); + m_lQuads.add(n); } } -void LAYER_QUADS::brush_flip_x() +void CLayerQuads::BrushFlipX() { } -void LAYER_QUADS::brush_flip_y() +void CLayerQuads::BrushFlipY() { } -void rotate(vec2 *center, vec2 *point, float rotation) +void Rotate(vec2 *pCenter, vec2 *pPoint, float Rotation) { - float x = point->x - center->x; - float y = point->y - center->y; - point->x = x * cosf(rotation) - y * sinf(rotation) + center->x; - point->y = x * sinf(rotation) + y * cosf(rotation) + center->y; + float x = pPoint->x - pCenter->x; + float y = pPoint->y - pCenter->y; + pPoint->x = x * cosf(Rotation) - y * sinf(Rotation) + pCenter->x; + pPoint->y = x * sinf(Rotation) + y * cosf(Rotation) + pCenter->y; } -void LAYER_QUADS::brush_rotate(float amount) +void CLayerQuads::BrushRotate(float Amount) { - vec2 center; - get_size(¢er.x, ¢er.y); - center.x /= 2; - center.y /= 2; + vec2 Center; + GetSize(&Center.x, &Center.y); + Center.x /= 2; + Center.y /= 2; - for(int i = 0; i < quads.len(); i++) + for(int i = 0; i < m_lQuads.size(); i++) { - QUAD *q = &quads[i]; + CQuad *q = &m_lQuads[i]; for(int p = 0; p < 5; p++) { - vec2 pos(fx2f(q->points[p].x), fx2f(q->points[p].y)); - rotate(¢er, &pos, amount); - q->points[p].x = f2fx(pos.x); - q->points[p].y = f2fx(pos.y); + vec2 Pos(fx2f(q->m_aPoints[p].x), fx2f(q->m_aPoints[p].y)); + Rotate(&Center, &Pos, Amount); + q->m_aPoints[p].x = f2fx(Pos.x); + q->m_aPoints[p].y = f2fx(Pos.y); } } } -void LAYER_QUADS::get_size(float *w, float *h) +void CLayerQuads::GetSize(float *w, float *h) { *w = 0; *h = 0; - for(int i = 0; i < quads.len(); i++) + for(int i = 0; i < m_lQuads.size(); i++) { for(int p = 0; p < 5; p++) { - *w = max(*w, fx2f(quads[i].points[p].x)); - *h = max(*h, fx2f(quads[i].points[p].y)); + *w = max(*w, fx2f(m_lQuads[i].m_aPoints[p].x)); + *h = max(*h, fx2f(m_lQuads[i].m_aPoints[p].y)); } } } -extern int selected_points; +extern int gs_SelectedPoints; -int LAYER_QUADS::render_properties(CUIRect *toolbox) +int CLayerQuads::RenderProperties(CUIRect *pToolBox) { // layer props enum @@ -216,37 +219,37 @@ int LAYER_QUADS::render_properties(CUIRect *toolbox) NUM_PROPS, }; - PROPERTY props[] = { - {"Image", image, PROPTYPE_IMAGE, -1, 0}, + CProperty aProps[] = { + {"Image", m_Image, PROPTYPE_IMAGE, -1, 0}, {0}, }; - static int ids[NUM_PROPS] = {0}; - int new_val = 0; - int prop = editor->do_properties(toolbox, props, ids, &new_val); + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal); - if(prop == PROP_IMAGE) + if(Prop == PROP_IMAGE) { - if(new_val >= 0) - image = new_val%editor->map.images.len(); + if(NewVal >= 0) + m_Image = NewVal%m_pEditor->m_Map.m_lImages.size(); else - image = -1; + m_Image = -1; } return 0; } -void LAYER_QUADS::modify_image_index(INDEX_MODIFY_FUNC func) +void CLayerQuads::ModifyImageIndex(INDEX_MODIFY_FUNC Func) { - func(&image); + Func(&m_Image); } -void LAYER_QUADS::modify_envelope_index(INDEX_MODIFY_FUNC func) +void CLayerQuads::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) { - for(int i = 0; i < quads.len(); i++) + for(int i = 0; i < m_lQuads.size(); i++) { - func(&quads[i].pos_env); - func(&quads[i].color_env); + Func(&m_lQuads[i].m_PosEnv); + Func(&m_lQuads[i].m_ColorEnv); } } diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp index 0d42cb78..ecd7c62c 100644 --- a/src/game/editor/ed_layer_tiles.cpp +++ b/src/game/editor/ed_layer_tiles.cpp @@ -1,247 +1,281 @@ -#include <base/math.hpp> +#include <base/math.h> -#include <engine/client/graphics.h> +#include <engine/graphics.h> +#include <engine/textrender.h> -#include <game/generated/gc_data.hpp> -#include <game/client/render.hpp> -#include "ed_editor.hpp" +#include <game/generated/client_data.h> +#include <game/client/render.h> +#include "ed_editor.h" -LAYER_TILES::LAYER_TILES(int w, int h) +CLayerTiles::CLayerTiles(int w, int h) { - type = LAYERTYPE_TILES; - type_name = "Tiles"; - width = w; - height = h; - image = -1; - tex_id = -1; - game = 0; + m_Type = LAYERTYPE_TILES; + m_pTypeName = "Tiles"; + m_Width = w; + m_Height = h; + m_Image = -1; + m_TexId = -1; + m_Game = 0; - tiles = new TILE[width*height]; - mem_zero(tiles, width*height*sizeof(TILE)); + m_pTiles = new CTile[m_Width*m_Height]; + mem_zero(m_pTiles, m_Width*m_Height*sizeof(CTile)); } -LAYER_TILES::~LAYER_TILES() +CLayerTiles::~CLayerTiles() { - delete [] tiles; + delete [] m_pTiles; } -void LAYER_TILES::prepare_for_save() +void CLayerTiles::PrepareForSave() { - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - tiles[y*width+x].flags &= TILEFLAG_VFLIP|TILEFLAG_HFLIP; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pTiles[y*m_Width+x].m_Flags &= TILEFLAG_VFLIP|TILEFLAG_HFLIP; - if(image != -1) + if(m_Image != -1) { - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - tiles[y*width+x].flags |= editor->map.images[image]->tileflags[tiles[y*width+x].index]; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pTiles[y*m_Width+x].m_Flags |= m_pEditor->m_Map.m_lImages[m_Image]->m_aTileFlags[m_pTiles[y*m_Width+x].m_Index]; } } -void LAYER_TILES::make_palette() +void CLayerTiles::MakePalette() { - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - tiles[y*width+x].index = y*16+x; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pTiles[y*m_Width+x].m_Index = y*16+x; } -void LAYER_TILES::render() +void CLayerTiles::Render() { - if(image >= 0 && image < editor->map.images.len()) - tex_id = editor->map.images[image]->tex_id; - Graphics()->TextureSet(tex_id); - editor->RenderTools()->render_tilemap(tiles, width, height, 32.0f, vec4(1,1,1,1), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT); + if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size()) + m_TexId = m_pEditor->m_Map.m_lImages[m_Image]->m_TexId; + Graphics()->TextureSet(m_TexId); + m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, vec4(1,1,1,1), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT); } -int LAYER_TILES::convert_x(float x) const { return (int)(x/32.0f); } -int LAYER_TILES::convert_y(float y) const { return (int)(y/32.0f); } +int CLayerTiles::ConvertX(float x) const { return (int)(x/32.0f); } +int CLayerTiles::ConvertY(float y) const { return (int)(y/32.0f); } -void LAYER_TILES::convert(CUIRect rect, RECTi *out) +void CLayerTiles::Convert(CUIRect Rect, RECTi *pOut) { - out->x = convert_x(rect.x); - out->y = convert_y(rect.y); - out->w = convert_x(rect.x+rect.w+31) - out->x; - out->h = convert_y(rect.y+rect.h+31) - out->y; + pOut->x = ConvertX(Rect.x); + pOut->y = ConvertY(Rect.y); + pOut->w = ConvertX(Rect.x+Rect.w+31) - pOut->x; + pOut->h = ConvertY(Rect.y+Rect.h+31) - pOut->y; } -void LAYER_TILES::snap(CUIRect *rect) +void CLayerTiles::Snap(CUIRect *pRect) { - RECTi out; - convert(*rect, &out); - rect->x = out.x*32.0f; - rect->y = out.y*32.0f; - rect->w = out.w*32.0f; - rect->h = out.h*32.0f; + RECTi Out; + Convert(*pRect, &Out); + pRect->x = Out.x*32.0f; + pRect->y = Out.y*32.0f; + pRect->w = Out.w*32.0f; + pRect->h = Out.h*32.0f; } -void LAYER_TILES::clamp(RECTi *rect) +void CLayerTiles::Clamp(RECTi *pRect) { - if(rect->x < 0) + if(pRect->x < 0) { - rect->w += rect->x; - rect->x = 0; + pRect->w += pRect->x; + pRect->x = 0; } - if(rect->y < 0) + if(pRect->y < 0) { - rect->h += rect->y; - rect->y = 0; + pRect->h += pRect->y; + pRect->y = 0; } - if(rect->x+rect->w > width) - rect->w = width-rect->x; + if(pRect->x+pRect->w > m_Width) + pRect->w = m_Width - pRect->x; - if(rect->y+rect->h > height) - rect->h = height-rect->y; + if(pRect->y+pRect->h > m_Height) + pRect->h = m_Height - pRect->y; - if(rect->h < 0) - rect->h = 0; - if(rect->w < 0) - rect->w = 0; + if(pRect->h < 0) + pRect->h = 0; + if(pRect->w < 0) + pRect->w = 0; } -void LAYER_TILES::brush_selecting(CUIRect rect) +void CLayerTiles::BrushSelecting(CUIRect Rect) { Graphics()->TextureSet(-1); - editor->Graphics()->QuadsBegin(); - editor->Graphics()->SetColor(1,1,1,0.4f); - snap(&rect); - editor->Graphics()->QuadsDrawTL(rect.x, rect.y, rect.w, rect.h); - editor->Graphics()->QuadsEnd(); - char buf[16]; - str_format(buf, sizeof(buf), "%d,%d", convert_x(rect.w), convert_y(rect.h)); - gfx_text(0, rect.x+3.0f, rect.y+3.0f, 15.0f*editor->world_zoom, buf, -1); + m_pEditor->Graphics()->QuadsBegin(); + m_pEditor->Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.4f); + Snap(&Rect); + IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h); + m_pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1); + m_pEditor->Graphics()->QuadsEnd(); + char aBuf[16]; + str_format(aBuf, sizeof(aBuf), "%d,%d", ConvertX(Rect.w), ConvertY(Rect.h)); + TextRender()->Text(0, Rect.x+3.0f, Rect.y+3.0f, 15.0f*m_pEditor->m_WorldZoom, aBuf, -1); } -int LAYER_TILES::brush_grab(LAYERGROUP *brush, CUIRect rect) +int CLayerTiles::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { RECTi r; - convert(rect, &r); - clamp(&r); + Convert(Rect, &r); + Clamp(&r); if(!r.w || !r.h) return 0; // create new layers - LAYER_TILES *grabbed = new LAYER_TILES(r.w, r.h); - grabbed->tex_id = tex_id; - grabbed->image = image; - brush->add_layer(grabbed); + CLayerTiles *pGrabbed = new CLayerTiles(r.w, r.h); + pGrabbed->m_pEditor = m_pEditor; + pGrabbed->m_TexId = m_TexId; + pGrabbed->m_Image = m_Image; + pBrush->AddLayer(pGrabbed); // copy the tiles for(int y = 0; y < r.h; y++) for(int x = 0; x < r.w; x++) - grabbed->tiles[y*grabbed->width+x] = tiles[(r.y+y)*width+(r.x+x)]; + pGrabbed->m_pTiles[y*pGrabbed->m_Width+x] = m_pTiles[(r.y+y)*m_Width+(r.x+x)]; return 1; } -void LAYER_TILES::brush_draw(LAYER *brush, float wx, float wy) +void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) { - if(readonly) + if(m_Readonly) + return; + + int sx = ConvertX(Rect.x); + int sy = ConvertY(Rect.y); + int w = ConvertX(Rect.w); + int h = ConvertY(Rect.h); + + CLayerTiles *pLt = static_cast<CLayerTiles*>(pBrush); + + for(int y = 0; y <= h; y++) + { + for(int x = 0; x <= w; x++) + { + int fx = x+sx; + int fy = y+sy; + + if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height) + continue; + + if(Empty) + m_pTiles[fy*m_Width+fx].m_Index = 1; + else + m_pTiles[fy*m_Width+fx] = pLt->m_pTiles[(y*pLt->m_Width + x%pLt->m_Width) % (pLt->m_Width*pLt->m_Height)]; + } + } +} + +void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy) +{ + if(m_Readonly) return; // - LAYER_TILES *l = (LAYER_TILES *)brush; - int sx = convert_x(wx); - int sy = convert_y(wy); + CLayerTiles *l = (CLayerTiles *)pBrush; + int sx = ConvertX(wx); + int sy = ConvertY(wy); - for(int y = 0; y < l->height; y++) - for(int x = 0; x < l->width; x++) + for(int y = 0; y < l->m_Height; y++) + for(int x = 0; x < l->m_Width; x++) { int fx = x+sx; int fy = y+sy; - if(fx<0 || fx >= width || fy < 0 || fy >= height) + if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height) continue; - tiles[fy*width+fx] = l->tiles[y*l->width+x]; + m_pTiles[fy*m_Width+fx] = l->m_pTiles[y*l->m_Width+x]; } } -void LAYER_TILES::brush_flip_x() +void CLayerTiles::BrushFlipX() { - for(int y = 0; y < height; y++) - for(int x = 0; x < width/2; x++) + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width/2; x++) { - TILE tmp = tiles[y*width+x]; - tiles[y*width+x] = tiles[y*width+width-1-x]; - tiles[y*width+width-1-x] = tmp; + CTile Tmp = m_pTiles[y*m_Width+x]; + m_pTiles[y*m_Width+x] = m_pTiles[y*m_Width+m_Width-1-x]; + m_pTiles[y*m_Width+m_Width-1-x] = Tmp; } - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - tiles[y*width+x].flags ^= TILEFLAG_VFLIP; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pTiles[y*m_Width+x].m_Flags ^= TILEFLAG_VFLIP; } -void LAYER_TILES::brush_flip_y() +void CLayerTiles::BrushFlipY() { - for(int y = 0; y < height/2; y++) - for(int x = 0; x < width; x++) + for(int y = 0; y < m_Height/2; y++) + for(int x = 0; x < m_Width; x++) { - TILE tmp = tiles[y*width+x]; - tiles[y*width+x] = tiles[(height-1-y)*width+x]; - tiles[(height-1-y)*width+x] = tmp; + CTile Tmp = m_pTiles[y*m_Width+x]; + m_pTiles[y*m_Width+x] = m_pTiles[(m_Height-1-y)*m_Width+x]; + m_pTiles[(m_Height-1-y)*m_Width+x] = Tmp; } - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - tiles[y*width+x].flags ^= TILEFLAG_HFLIP; + for(int y = 0; y < m_Height; y++) + for(int x = 0; x < m_Width; x++) + m_pTiles[y*m_Width+x].m_Flags ^= TILEFLAG_HFLIP; } -void LAYER_TILES::resize(int new_w, int new_h) +void CLayerTiles::Resize(int NewW, int NewH) { - TILE *new_data = new TILE[new_w*new_h]; - mem_zero(new_data, new_w*new_h*sizeof(TILE)); + CTile *pNewData = new CTile[NewW*NewH]; + mem_zero(pNewData, NewW*NewH*sizeof(CTile)); // copy old data - for(int y = 0; y < min(new_h, height); y++) - mem_copy(&new_data[y*new_w], &tiles[y*width], min(width, new_w)*sizeof(TILE)); + for(int y = 0; y < min(NewH, m_Height); y++) + mem_copy(&pNewData[y*NewW], &m_pTiles[y*m_Width], min(m_Width, NewW)*sizeof(CTile)); // replace old - delete [] tiles; - tiles = new_data; - width = new_w; - height = new_h; + delete [] m_pTiles; + m_pTiles = pNewData; + m_Width = NewW; + m_Height = NewH; } -int LAYER_TILES::render_properties(CUIRect *toolbox) +int CLayerTiles::RenderProperties(CUIRect *pToolBox) { - CUIRect button; - toolbox->HSplitBottom(12.0f, toolbox, &button); - bool in_gamegroup = editor->map.game_group->layers.find(this) != -1; - if(editor->map.game_layer == this) - in_gamegroup = false; - static int colcl_button = 0; - if(editor->DoButton_Editor(&colcl_button, "Clear Collision", in_gamegroup?0:-1, &button, 0, "Removes collision from this layer")) + CUIRect Button; + pToolBox->HSplitBottom(12.0f, pToolBox, &Button); + + bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty(); + if(m_pEditor->m_Map.m_pGameLayer == this) + InGameGroup = false; + static int s_ColclButton = 0; + if(m_pEditor->DoButton_Editor(&s_ColclButton, "Clear Collision", InGameGroup?0:-1, &Button, 0, "Removes collision from this layer")) { - LAYER_TILES *gl = editor->map.game_layer; - int w = min(gl->width, width); - int h = min(gl->height, height); + CLayerTiles *gl = m_pEditor->m_Map.m_pGameLayer; + int w = min(gl->m_Width, m_Width); + int h = min(gl->m_Height, m_Height); for(int y = 0; y < h; y++) for(int x = 0; x < w; x++) { - if(gl->tiles[y*gl->width+x].index <= TILE_SOLID) - if(tiles[y*width+x].index) - gl->tiles[y*gl->width+x].index = TILE_AIR; + if(gl->m_pTiles[y*gl->m_Width+x].m_Index <= TILE_SOLID) + if(m_pTiles[y*m_Width+x].m_Index) + gl->m_pTiles[y*gl->m_Width+x].m_Index = TILE_AIR; } return 1; } - static int col_button = 0; - toolbox->HSplitBottom(5.0f, toolbox, &button); - toolbox->HSplitBottom(12.0f, toolbox, &button); - if(editor->DoButton_Editor(&col_button, "Make Collision", in_gamegroup?0:-1, &button, 0, "Constructs collision from this layer")) + static int s_ColButton = 0; + pToolBox->HSplitBottom(5.0f, pToolBox, &Button); + pToolBox->HSplitBottom(12.0f, pToolBox, &Button); + if(m_pEditor->DoButton_Editor(&s_ColButton, "Make Collision", InGameGroup?0:-1, &Button, 0, "Constructs collision from this layer")) { - LAYER_TILES *gl = editor->map.game_layer; - int w = min(gl->width, width); - int h = min(gl->height, height); + CLayerTiles *gl = m_pEditor->m_Map.m_pGameLayer; + int w = min(gl->m_Width, m_Width); + int h = min(gl->m_Height, m_Height); for(int y = 0; y < h; y++) for(int x = 0; x < w; x++) { - if(gl->tiles[y*gl->width+x].index <= TILE_SOLID) - gl->tiles[y*gl->width+x].index = tiles[y*width+x].index?TILE_SOLID:TILE_AIR; + if(gl->m_pTiles[y*gl->m_Width+x].m_Index <= TILE_SOLID) + gl->m_pTiles[y*gl->m_Width+x].m_Index = m_pTiles[y*m_Width+x].m_Index?TILE_SOLID:TILE_AIR; } return 1; @@ -255,44 +289,44 @@ int LAYER_TILES::render_properties(CUIRect *toolbox) NUM_PROPS, }; - PROPERTY props[] = { - {"Width", width, PROPTYPE_INT_STEP, 1, 1000000000}, - {"Height", height, PROPTYPE_INT_STEP, 1, 1000000000}, - {"Image", image, PROPTYPE_IMAGE, 0, 0}, + CProperty aProps[] = { + {"Width", m_Width, PROPTYPE_INT_STEP, 1, 1000000000}, + {"Height", m_Height, PROPTYPE_INT_STEP, 1, 1000000000}, + {"Image", m_Image, PROPTYPE_IMAGE, 0, 0}, {0}, }; - if(editor->map.game_layer == this) // remove the image from the selection if this is the game layer - props[2].name = 0; + if(m_pEditor->m_Map.m_pGameLayer == this) // remove the image from the selection if this is the game layer + aProps[2].m_pName = 0; - static int ids[NUM_PROPS] = {0}; - int new_val = 0; - int prop = editor->do_properties(toolbox, props, ids, &new_val); + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal); - if(prop == PROP_WIDTH && new_val > 1) - resize(new_val, height); - else if(prop == PROP_HEIGHT && new_val > 1) - resize(width, new_val); - else if(prop == PROP_IMAGE) + if(Prop == PROP_WIDTH && NewVal > 1) + Resize(NewVal, m_Height); + else if(Prop == PROP_HEIGHT && NewVal > 1) + Resize(m_Width, NewVal); + else if(Prop == PROP_IMAGE) { - if (new_val == -1) + if (NewVal == -1) { - tex_id = -1; - image = -1; + m_TexId = -1; + m_Image = -1; } else - image = new_val%editor->map.images.len(); + m_Image = NewVal%m_pEditor->m_Map.m_lImages.size(); } return 0; } -void LAYER_TILES::modify_image_index(INDEX_MODIFY_FUNC func) +void CLayerTiles::ModifyImageIndex(INDEX_MODIFY_FUNC Func) { - func(&image); + Func(&m_Image); } -void LAYER_TILES::modify_envelope_index(INDEX_MODIFY_FUNC func) +void CLayerTiles::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) { } diff --git a/src/game/editor/ed_popups.cpp b/src/game/editor/ed_popups.cpp index 59140153..2e58ae3a 100644 --- a/src/game/editor/ed_popups.cpp +++ b/src/game/editor/ed_popups.cpp @@ -1,111 +1,114 @@ -#include <stdio.h> -#include <engine/client/graphics.h> -#include "ed_editor.hpp" +#include <engine/graphics.h> +#include <engine/input.h> +#include <engine/keys.h> +#include "ed_editor.h" // popup menu handling static struct { - CUIRect rect; - void *id; - int (*func)(EDITOR *pEditor, CUIRect rect); - int is_menu; - void *extra; -} ui_popups[8]; + CUIRect m_Rect; + void *m_pId; + int (*m_pfnFunc)(CEditor *pEditor, CUIRect Rect); + int m_IsMenu; + void *m_pExtra; +} s_UiPopups[8]; -static int ui_num_popups = 0; +static int g_UiNumPopups = 0; -void EDITOR::ui_invoke_popup_menu(void *id, int flags, float x, float y, float w, float h, int (*func)(EDITOR *pEditor, CUIRect rect), void *extra) +void CEditor::UiInvokePopupMenu(void *Id, int Flags, float x, float y, float w, float h, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra) { dbg_msg("", "invoked"); - ui_popups[ui_num_popups].id = id; - ui_popups[ui_num_popups].is_menu = flags; - ui_popups[ui_num_popups].rect.x = x; - ui_popups[ui_num_popups].rect.y = y; - ui_popups[ui_num_popups].rect.w = w; - ui_popups[ui_num_popups].rect.h = h; - ui_popups[ui_num_popups].func = func; - ui_popups[ui_num_popups].extra = extra; - ui_num_popups++; + s_UiPopups[g_UiNumPopups].m_pId = Id; + s_UiPopups[g_UiNumPopups].m_IsMenu = Flags; + s_UiPopups[g_UiNumPopups].m_Rect.x = x; + s_UiPopups[g_UiNumPopups].m_Rect.y = y; + s_UiPopups[g_UiNumPopups].m_Rect.w = w; + s_UiPopups[g_UiNumPopups].m_Rect.h = h; + s_UiPopups[g_UiNumPopups].m_pfnFunc = pfnFunc; + s_UiPopups[g_UiNumPopups].m_pExtra = pExtra; + g_UiNumPopups++; } -void EDITOR::ui_do_popup_menu() +void CEditor::UiDoPopupMenu() { - for(int i = 0; i < ui_num_popups; i++) + for(int i = 0; i < g_UiNumPopups; i++) { - bool inside = UI()->MouseInside(&ui_popups[i].rect); - UI()->SetHotItem(&ui_popups[i].id); + bool Inside = UI()->MouseInside(&s_UiPopups[i].m_Rect); + UI()->SetHotItem(&s_UiPopups[i].m_pId); - if(UI()->ActiveItem() == &ui_popups[i].id) + if(UI()->ActiveItem() == &s_UiPopups[i].m_pId) { if(!UI()->MouseButton(0)) { - if(!inside) - ui_num_popups--; + if(!Inside) + g_UiNumPopups--; UI()->SetActiveItem(0); } } - else if(UI()->HotItem() == &ui_popups[i].id) + else if(UI()->HotItem() == &s_UiPopups[i].m_pId) { if(UI()->MouseButton(0)) - UI()->SetActiveItem(&ui_popups[i].id); + UI()->SetActiveItem(&s_UiPopups[i].m_pId); } - int corners = CUI::CORNER_ALL; - if(ui_popups[i].is_menu) - corners = CUI::CORNER_R|CUI::CORNER_B; + int Corners = CUI::CORNER_ALL; + if(s_UiPopups[i].m_IsMenu) + Corners = CUI::CORNER_R|CUI::CORNER_B; - CUIRect r = ui_popups[i].rect; - RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), corners, 3.0f); + CUIRect r = s_UiPopups[i].m_Rect; + RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), Corners, 3.0f); r.Margin(1.0f, &r); - RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), corners, 3.0f); + RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), Corners, 3.0f); r.Margin(4.0f, &r); - if(ui_popups[i].func(this, r)) - ui_num_popups--; + if(s_UiPopups[i].m_pfnFunc(this, r)) + g_UiNumPopups--; - if(inp_key_down(KEY_ESCAPE)) - ui_num_popups--; + if(Input()->KeyDown(KEY_ESCAPE)) + g_UiNumPopups--; } } -int EDITOR::popup_group(EDITOR *pEditor, CUIRect view) +int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) { // remove group button - CUIRect button; - view.HSplitBottom(12.0f, &view, &button); - static int delete_button = 0; + CUIRect Button; + View.HSplitBottom(12.0f, &View, &Button); + static int s_DeleteButton = 0; // don't allow deletion of game group - if(pEditor->map.game_group != pEditor->get_selected_group() && - pEditor->DoButton_Editor(&delete_button, "Delete Group", 0, &button, 0, "Delete group")) + if(pEditor->m_Map.m_pGameGroup != pEditor->GetSelectedGroup() && + pEditor->DoButton_Editor(&s_DeleteButton, "Delete Group", 0, &Button, 0, "Delete group")) { - pEditor->map.delete_group(pEditor->selected_group); + pEditor->m_Map.DeleteGroup(pEditor->m_SelectedGroup); return 1; } // new tile layer - view.HSplitBottom(10.0f, &view, &button); - view.HSplitBottom(12.0f, &view, &button); - static int new_quad_layer_button = 0; - if(pEditor->DoButton_Editor(&new_quad_layer_button, "Add Quads Layer", 0, &button, 0, "Creates a new quad layer")) + View.HSplitBottom(10.0f, &View, &Button); + View.HSplitBottom(12.0f, &View, &Button); + static int s_NewQuadLayerButton = 0; + if(pEditor->DoButton_Editor(&s_NewQuadLayerButton, "Add Quads Layer", 0, &Button, 0, "Creates a new quad layer")) { - LAYER *l = new LAYER_QUADS; - pEditor->map.groups[pEditor->selected_group]->add_layer(l); - pEditor->selected_layer = pEditor->map.groups[pEditor->selected_group]->layers.len()-1; + CLayer *l = new CLayerQuads; + l->m_pEditor = pEditor; + pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l); + pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1; return 1; } // new quad layer - view.HSplitBottom(5.0f, &view, &button); - view.HSplitBottom(12.0f, &view, &button); - static int new_tile_layer_button = 0; - if(pEditor->DoButton_Editor(&new_tile_layer_button, "Add Tile Layer", 0, &button, 0, "Creates a new tile layer")) + View.HSplitBottom(5.0f, &View, &Button); + View.HSplitBottom(12.0f, &View, &Button); + static int s_NewTileLayerButton = 0; + if(pEditor->DoButton_Editor(&s_NewTileLayerButton, "Add Tile Layer", 0, &Button, 0, "Creates a new tile layer")) { - LAYER *l = new LAYER_TILES(50, 50); - pEditor->map.groups[pEditor->selected_group]->add_layer(l); - pEditor->selected_layer = pEditor->map.groups[pEditor->selected_group]->layers.len()-1; + CLayer *l = new CLayerTiles(50, 50); + l->m_pEditor = pEditor; + pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l); + pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1; return 1; } @@ -124,68 +127,68 @@ int EDITOR::popup_group(EDITOR *pEditor, CUIRect view) NUM_PROPS, }; - PROPERTY props[] = { - {"Order", pEditor->selected_group, PROPTYPE_INT_STEP, 0, pEditor->map.groups.len()-1}, - {"Pos X", -pEditor->map.groups[pEditor->selected_group]->offset_x, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Pos Y", -pEditor->map.groups[pEditor->selected_group]->offset_y, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Para X", pEditor->map.groups[pEditor->selected_group]->parallax_x, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Para Y", pEditor->map.groups[pEditor->selected_group]->parallax_y, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - - {"Use Clipping", pEditor->map.groups[pEditor->selected_group]->use_clipping, PROPTYPE_BOOL, 0, 1}, - {"Clip X", pEditor->map.groups[pEditor->selected_group]->clip_x, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Clip Y", pEditor->map.groups[pEditor->selected_group]->clip_y, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Clip W", pEditor->map.groups[pEditor->selected_group]->clip_w, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Clip H", pEditor->map.groups[pEditor->selected_group]->clip_h, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + CProperty aProps[] = { + {"Order", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1}, + {"Pos X", -pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetX, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Pos Y", -pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetY, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Para X", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxX, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Para Y", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxY, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + + {"Use Clipping", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_UseClipping, PROPTYPE_BOOL, 0, 1}, + {"Clip X", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipX, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Clip Y", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipY, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Clip W", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipW, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Clip H", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {0}, }; - static int ids[NUM_PROPS] = {0}; - int new_val = 0; + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; // cut the properties that isn't needed - if(pEditor->get_selected_group()->game_group) - props[PROP_POS_X].name = 0; + if(pEditor->GetSelectedGroup()->m_GameGroup) + aProps[PROP_POS_X].m_pName = 0; - int prop = pEditor->do_properties(&view, props, ids, &new_val); - if(prop == PROP_ORDER) - pEditor->selected_group = pEditor->map.swap_groups(pEditor->selected_group, new_val); + int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); + if(Prop == PROP_ORDER) + pEditor->m_SelectedGroup = pEditor->m_Map.SwapGroups(pEditor->m_SelectedGroup, NewVal); // these can not be changed on the game group - if(!pEditor->get_selected_group()->game_group) + if(!pEditor->GetSelectedGroup()->m_GameGroup) { - if(prop == PROP_PARA_X) pEditor->map.groups[pEditor->selected_group]->parallax_x = new_val; - else if(prop == PROP_PARA_Y) pEditor->map.groups[pEditor->selected_group]->parallax_y = new_val; - else if(prop == PROP_POS_X) pEditor->map.groups[pEditor->selected_group]->offset_x = -new_val; - else if(prop == PROP_POS_Y) pEditor->map.groups[pEditor->selected_group]->offset_y = -new_val; - else if(prop == PROP_USE_CLIPPING) pEditor->map.groups[pEditor->selected_group]->use_clipping = new_val; - else if(prop == PROP_CLIP_X) pEditor->map.groups[pEditor->selected_group]->clip_x = new_val; - else if(prop == PROP_CLIP_Y) pEditor->map.groups[pEditor->selected_group]->clip_y = new_val; - else if(prop == PROP_CLIP_W) pEditor->map.groups[pEditor->selected_group]->clip_w = new_val; - else if(prop == PROP_CLIP_H) pEditor->map.groups[pEditor->selected_group]->clip_h = new_val; + if(Prop == PROP_PARA_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxX = NewVal; + else if(Prop == PROP_PARA_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ParallaxY = NewVal; + else if(Prop == PROP_POS_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetX = -NewVal; + else if(Prop == PROP_POS_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetY = -NewVal; + else if(Prop == PROP_USE_CLIPPING) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_UseClipping = NewVal; + else if(Prop == PROP_CLIP_X) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipX = NewVal; + else if(Prop == PROP_CLIP_Y) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipY = NewVal; + else if(Prop == PROP_CLIP_W) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipW = NewVal; + else if(Prop == PROP_CLIP_H) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH = NewVal; } return 0; } -int EDITOR::popup_layer(EDITOR *pEditor, CUIRect view) +int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) { // remove layer button - CUIRect button; - view.HSplitBottom(12.0f, &view, &button); - static int delete_button = 0; + CUIRect Button; + View.HSplitBottom(12.0f, &View, &Button); + static int s_DeleteButton = 0; // don't allow deletion of game layer - if(pEditor->map.game_layer != pEditor->get_selected_layer(0) && - pEditor->DoButton_Editor(&delete_button, "Delete Layer", 0, &button, 0, "Deletes the layer")) + if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) && + pEditor->DoButton_Editor(&s_DeleteButton, "Delete Layer", 0, &Button, 0, "Deletes the layer")) { - pEditor->map.groups[pEditor->selected_group]->delete_layer(pEditor->selected_layer); + pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->DeleteLayer(pEditor->m_SelectedLayer); return 1; } - view.HSplitBottom(10.0f, &view, 0); + View.HSplitBottom(10.0f, &View, 0); - LAYERGROUP *current_group = pEditor->map.groups[pEditor->selected_group]; - LAYER *current_layer = pEditor->get_selected_layer(0); + CLayerGroup *pCurrentGroup = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]; + CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0); enum { @@ -195,82 +198,88 @@ int EDITOR::popup_layer(EDITOR *pEditor, CUIRect view) NUM_PROPS, }; - PROPERTY props[] = { - {"Group", pEditor->selected_group, PROPTYPE_INT_STEP, 0, pEditor->map.groups.len()-1}, - {"Order", pEditor->selected_layer, PROPTYPE_INT_STEP, 0, current_group->layers.len()}, - {"Detail", current_layer->flags&LAYERFLAG_DETAIL, PROPTYPE_BOOL, 0, 1}, + CProperty aProps[] = { + {"Group", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1}, + {"Order", pEditor->m_SelectedLayer, PROPTYPE_INT_STEP, 0, pCurrentGroup->m_lLayers.size()}, + {"Detail", pCurrentLayer->m_Flags&LAYERFLAG_DETAIL, PROPTYPE_BOOL, 0, 1}, {0}, }; + + if(pEditor->m_Map.m_pGameLayer == pEditor->GetSelectedLayer(0)) // dont use Group and Detail from the selection if this is the game layer + { + aProps[0].m_Type = PROPTYPE_NULL; + aProps[2].m_Type = PROPTYPE_NULL; + } - static int ids[NUM_PROPS] = {0}; - int new_val = 0; - int prop = pEditor->do_properties(&view, props, ids, &new_val); + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); - if(prop == PROP_ORDER) - pEditor->selected_layer = current_group->swap_layers(pEditor->selected_layer, new_val); - else if(prop == PROP_GROUP && current_layer->type != LAYERTYPE_GAME) + if(Prop == PROP_ORDER) + pEditor->m_SelectedLayer = pCurrentGroup->SwapLayers(pEditor->m_SelectedLayer, NewVal); + else if(Prop == PROP_GROUP && pCurrentLayer->m_Type != LAYERTYPE_GAME) { - if(new_val >= 0 && new_val < pEditor->map.groups.len()) + if(NewVal >= 0 && NewVal < pEditor->m_Map.m_lGroups.size()) { - current_group->layers.remove(current_layer); - pEditor->map.groups[new_val]->layers.add(current_layer); - pEditor->selected_group = new_val; - pEditor->selected_layer = pEditor->map.groups[new_val]->layers.len()-1; + pCurrentGroup->m_lLayers.remove(pCurrentLayer); + pEditor->m_Map.m_lGroups[NewVal]->m_lLayers.add(pCurrentLayer); + pEditor->m_SelectedGroup = NewVal; + pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[NewVal]->m_lLayers.size()-1; } } - else if(prop == PROP_HQ) + else if(Prop == PROP_HQ) { - current_layer->flags &= ~LAYERFLAG_DETAIL; - if(new_val) - current_layer->flags |= LAYERFLAG_DETAIL; + pCurrentLayer->m_Flags &= ~LAYERFLAG_DETAIL; + if(NewVal) + pCurrentLayer->m_Flags |= LAYERFLAG_DETAIL; } - return current_layer->render_properties(&view); + return pCurrentLayer->RenderProperties(&View); } -int EDITOR::popup_quad(EDITOR *pEditor, CUIRect view) +int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) { - QUAD *quad = pEditor->get_selected_quad(); + CQuad *pQuad = pEditor->GetSelectedQuad(); - CUIRect button; + CUIRect Button; // delete button - view.HSplitBottom(12.0f, &view, &button); - static int delete_button = 0; - if(pEditor->DoButton_Editor(&delete_button, "Delete", 0, &button, 0, "Deletes the current quad")) + View.HSplitBottom(12.0f, &View, &Button); + static int s_DeleteButton = 0; + if(pEditor->DoButton_Editor(&s_DeleteButton, "Delete", 0, &Button, 0, "Deletes the current quad")) { - LAYER_QUADS *layer = (LAYER_QUADS *)pEditor->get_selected_layer_type(0, LAYERTYPE_QUADS); - if(layer) + CLayerQuads *pLayer = (CLayerQuads *)pEditor->GetSelectedLayerType(0, LAYERTYPE_QUADS); + if(pLayer) { - layer->quads.removebyindex(pEditor->selected_quad); - pEditor->selected_quad--; + pLayer->m_lQuads.remove_index(pEditor->m_SelectedQuad); + pEditor->m_SelectedQuad--; } return 1; } // square button - view.HSplitBottom(10.0f, &view, &button); - view.HSplitBottom(12.0f, &view, &button); - static int sq_button = 0; - if(pEditor->DoButton_Editor(&sq_button, "Square", 0, &button, 0, "Squares the current quad")) + View.HSplitBottom(10.0f, &View, &Button); + View.HSplitBottom(12.0f, &View, &Button); + static int s_Button = 0; + if(pEditor->DoButton_Editor(&s_Button, "Square", 0, &Button, 0, "Squares the current quad")) { - int top = quad->points[0].y; - int left = quad->points[0].x; - int bottom = quad->points[0].y; - int right = quad->points[0].x; + int Top = pQuad->m_aPoints[0].y; + int Left = pQuad->m_aPoints[0].x; + int Bottom = pQuad->m_aPoints[0].y; + int Right = pQuad->m_aPoints[0].x; for(int k = 1; k < 4; k++) { - if(quad->points[k].y < top) top = quad->points[k].y; - if(quad->points[k].x < left) left = quad->points[k].x; - if(quad->points[k].y > bottom) bottom = quad->points[k].y; - if(quad->points[k].x > right) right = quad->points[k].x; + if(pQuad->m_aPoints[k].y < Top) Top = pQuad->m_aPoints[k].y; + if(pQuad->m_aPoints[k].x < Left) Left = pQuad->m_aPoints[k].x; + if(pQuad->m_aPoints[k].y > Bottom) Bottom = pQuad->m_aPoints[k].y; + if(pQuad->m_aPoints[k].x > Right) Right = pQuad->m_aPoints[k].x; } - quad->points[0].x = left; quad->points[0].y = top; - quad->points[1].x = right; quad->points[1].y = top; - quad->points[2].x = left; quad->points[2].y = bottom; - quad->points[3].x = right; quad->points[3].y = bottom; + pQuad->m_aPoints[0].x = Left; pQuad->m_aPoints[0].y = Top; + pQuad->m_aPoints[1].x = Right; pQuad->m_aPoints[1].y = Top; + pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Bottom; + pQuad->m_aPoints[3].x = Right; pQuad->m_aPoints[3].y = Bottom; return 1; } @@ -284,30 +293,30 @@ int EDITOR::popup_quad(EDITOR *pEditor, CUIRect view) NUM_PROPS, }; - PROPERTY props[] = { - {"Pos. Env", quad->pos_env, PROPTYPE_INT_STEP, -1, pEditor->map.envelopes.len()}, - {"Pos. TO", quad->pos_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - {"Color Env", quad->color_env, PROPTYPE_INT_STEP, -1, pEditor->map.envelopes.len()}, - {"Color TO", quad->color_env_offset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + CProperty aProps[] = { + {"Pos. Env", pQuad->m_PosEnv, PROPTYPE_INT_STEP, -1, pEditor->m_Map.m_lEnvelopes.size()}, + {"Pos. TO", pQuad->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, + {"Color Env", pQuad->m_ColorEnv, PROPTYPE_INT_STEP, -1, pEditor->m_Map.m_lEnvelopes.size()}, + {"Color TO", pQuad->m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {0}, }; - static int ids[NUM_PROPS] = {0}; - int new_val = 0; - int prop = pEditor->do_properties(&view, props, ids, &new_val); + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); - if(prop == PROP_POS_ENV) quad->pos_env = clamp(new_val, -1, pEditor->map.envelopes.len()-1); - if(prop == PROP_POS_ENV_OFFSET) quad->pos_env_offset = new_val; - if(prop == PROP_COLOR_ENV) quad->color_env = clamp(new_val, -1, pEditor->map.envelopes.len()-1); - if(prop == PROP_COLOR_ENV_OFFSET) quad->color_env_offset = new_val; + if(Prop == PROP_POS_ENV) pQuad->m_PosEnv = clamp(NewVal, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + if(Prop == PROP_POS_ENV_OFFSET) pQuad->m_PosEnvOffset = NewVal; + if(Prop == PROP_COLOR_ENV) pQuad->m_ColorEnv = clamp(NewVal, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + if(Prop == PROP_COLOR_ENV_OFFSET) pQuad->m_ColorEnvOffset = NewVal; return 0; } -int EDITOR::popup_point(EDITOR *pEditor, CUIRect view) +int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) { - QUAD *quad = pEditor->get_selected_quad(); + CQuad *pQuad = pEditor->GetSelectedQuad(); enum { @@ -315,40 +324,40 @@ int EDITOR::popup_point(EDITOR *pEditor, CUIRect view) NUM_PROPS, }; - int color = 0; + int Color = 0; for(int v = 0; v < 4; v++) { - if(pEditor->selected_points&(1<<v)) + if(pEditor->m_SelectedPoints&(1<<v)) { - color = 0; - color |= quad->colors[v].r<<24; - color |= quad->colors[v].g<<16; - color |= quad->colors[v].b<<8; - color |= quad->colors[v].a; + Color = 0; + Color |= pQuad->m_aColors[v].r<<24; + Color |= pQuad->m_aColors[v].g<<16; + Color |= pQuad->m_aColors[v].b<<8; + Color |= pQuad->m_aColors[v].a; } } - PROPERTY props[] = { - {"Color", color, PROPTYPE_COLOR, -1, pEditor->map.envelopes.len()}, + CProperty aProps[] = { + {"Color", Color, PROPTYPE_COLOR, -1, pEditor->m_Map.m_lEnvelopes.size()}, {0}, }; - static int ids[NUM_PROPS] = {0}; - int new_val = 0; - int prop = pEditor->do_properties(&view, props, ids, &new_val); - if(prop == PROP_COLOR) + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); + if(Prop == PROP_COLOR) { for(int v = 0; v < 4; v++) { - if(pEditor->selected_points&(1<<v)) + if(pEditor->m_SelectedPoints&(1<<v)) { - color = 0; - quad->colors[v].r = (new_val>>24)&0xff; - quad->colors[v].g = (new_val>>16)&0xff; - quad->colors[v].b = (new_val>>8)&0xff; - quad->colors[v].a = new_val&0xff; + Color = 0; + pQuad->m_aColors[v].r = (NewVal>>24)&0xff; + pQuad->m_aColors[v].g = (NewVal>>16)&0xff; + pQuad->m_aColors[v].b = (NewVal>>8)&0xff; + pQuad->m_aColors[v].a = NewVal&0xff; } } } @@ -358,65 +367,66 @@ int EDITOR::popup_point(EDITOR *pEditor, CUIRect view) -static int select_image_selected = -100; -static int select_image_current = -100; +static int g_SelectImageSelected = -100; +static int g_SelectImageCurrent = -100; -int EDITOR::popup_select_image(EDITOR *pEditor, CUIRect view) +int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View) { - CUIRect buttonbar, imageview; - view.VSplitLeft(80.0f, &buttonbar, &view); - view.Margin(10.0f, &imageview); + CUIRect ButtonBar, ImageView; + View.VSplitLeft(80.0f, &ButtonBar, &View); + View.Margin(10.0f, &ImageView); - int show_image = select_image_current; + int ShowImage = g_SelectImageCurrent; - for(int i = -1; i < pEditor->map.images.len(); i++) + for(int i = -1; i < pEditor->m_Map.m_lImages.size(); i++) { - CUIRect button; - buttonbar.HSplitTop(12.0f, &button, &buttonbar); - buttonbar.HSplitTop(2.0f, 0, &buttonbar); + CUIRect Button; + ButtonBar.HSplitTop(12.0f, &Button, &ButtonBar); + ButtonBar.HSplitTop(2.0f, 0, &ButtonBar); - if(pEditor->UI()->MouseInside(&button)) - show_image = i; + if(pEditor->UI()->MouseInside(&Button)) + ShowImage = i; if(i == -1) { - if(pEditor->DoButton_MenuItem(&pEditor->map.images[i], "None", i==select_image_current, &button)) - select_image_selected = -1; + if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], "None", i==g_SelectImageCurrent, &Button)) + g_SelectImageSelected = -1; } else { - if(pEditor->DoButton_MenuItem(&pEditor->map.images[i], pEditor->map.images[i]->name, i==select_image_current, &button)) - select_image_selected = i; + if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], pEditor->m_Map.m_lImages[i]->m_aName, i==g_SelectImageCurrent, &Button)) + g_SelectImageSelected = i; } } - if(show_image >= 0 && show_image < pEditor->map.images.len()) - pEditor->Graphics()->TextureSet(pEditor->map.images[show_image]->tex_id); + if(ShowImage >= 0 && ShowImage < pEditor->m_Map.m_lImages.size()) + pEditor->Graphics()->TextureSet(pEditor->m_Map.m_lImages[ShowImage]->m_TexId); else pEditor->Graphics()->TextureSet(-1); pEditor->Graphics()->QuadsBegin(); - pEditor->Graphics()->QuadsDrawTL(imageview.x, imageview.y, imageview.w, imageview.h); + IGraphics::CQuadItem QuadItem(ImageView.x, ImageView.y, ImageView.w, ImageView.h); + pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1); pEditor->Graphics()->QuadsEnd(); return 0; } -void EDITOR::popup_select_image_invoke(int current, float x, float y) +void CEditor::PopupSelectImageInvoke(int Current, float x, float y) { - static int select_image_popup_id = 0; - select_image_selected = -100; - select_image_current = current; - ui_invoke_popup_menu(&select_image_popup_id, 0, x, y, 400, 300, popup_select_image); + static int s_SelectImagePopupId = 0; + g_SelectImageSelected = -100; + g_SelectImageCurrent = Current; + UiInvokePopupMenu(&s_SelectImagePopupId, 0, x, y, 400, 300, PopupSelectImage); } -int EDITOR::popup_select_image_result() +int CEditor::PopupSelectImageResult() { - if(select_image_selected == -100) + if(g_SelectImageSelected == -100) return -100; - select_image_current = select_image_selected; - select_image_selected = -100; - return select_image_current; + g_SelectImageCurrent = g_SelectImageSelected; + g_SelectImageSelected = -100; + return g_SelectImageCurrent; } diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index ceb63be3..f5aa18cf 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -1,417 +1,311 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <string.h> -#include "gamecore.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include "gamecore.h" -const char *TUNING_PARAMS::names[] = +const char *CTuningParams::m_apNames[] = { - #define MACRO_TUNING_PARAM(name,value) #name, - #include "tuning.hpp" + #define MACRO_TUNING_PARAM(Name,ScriptName,Value) #ScriptName, + #include "tuning.h" #undef MACRO_TUNING_PARAM }; -bool TUNING_PARAMS::set(int index, float value) +bool CTuningParams::Set(int Index, float Value) { - if(index < 0 || index >= num()) + if(Index < 0 || Index >= Num()) return false; - ((tune_param *)this)[index] = value; + ((CTuneParam *)this)[Index] = Value; return true; } -bool TUNING_PARAMS::get(int index, float *value) +bool CTuningParams::Get(int Index, float *pValue) { - if(index < 0 || index >= num()) + if(Index < 0 || Index >= Num()) return false; - *value = (float)((tune_param *)this)[index]; + *pValue = (float)((CTuneParam *)this)[Index]; return true; } -bool TUNING_PARAMS::set(const char *name, float value) +bool CTuningParams::Set(const char *pName, float Value) { - for(int i = 0; i < num(); i++) - if(strcmp(name, names[i]) == 0) - return set(i, value); + for(int i = 0; i < Num(); i++) + if(str_comp_nocase(pName, m_apNames[i]) == 0) + return Set(i, Value); return false; } -bool TUNING_PARAMS::get(const char *name, float *value) +bool CTuningParams::Get(const char *pName, float *pValue) { - for(int i = 0; i < num(); i++) - if(strcmp(name, names[i]) == 0) - return get(i, value); + for(int i = 0; i < Num(); i++) + if(str_comp_nocase(pName, m_apNames[i]) == 0) + return Get(i, pValue); return false; } -// TODO: OPT: rewrite this smarter! -void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces) +float HermiteBasis1(float v) { - if(bounces) - *bounces = 0; - - vec2 pos = *inout_pos; - vec2 vel = *inout_vel; - if(col_check_point(pos + vel)) - { - int affected = 0; - if(col_check_point(pos.x + vel.x, pos.y)) - { - inout_vel->x *= -elasticity; - if(bounces) - (*bounces)++; - affected++; - } - - if(col_check_point(pos.x, pos.y + vel.y)) - { - inout_vel->y *= -elasticity; - if(bounces) - (*bounces)++; - affected++; - } - - if(affected == 0) - { - inout_vel->x *= -elasticity; - inout_vel->y *= -elasticity; - } - } - else - { - *inout_pos = pos + vel; - } -} - -bool test_box(vec2 pos, vec2 size) -{ - size *= 0.5f; - if(col_check_point(pos.x-size.x, pos.y-size.y)) - return true; - if(col_check_point(pos.x+size.x, pos.y-size.y)) - return true; - if(col_check_point(pos.x-size.x, pos.y+size.y)) - return true; - if(col_check_point(pos.x+size.x, pos.y+size.y)) - return true; - return false; -} - -void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity) -{ - // do the move - vec2 pos = *inout_pos; - vec2 vel = *inout_vel; - - float distance = length(vel); - int max = (int)distance; - - if(distance > 0.00001f) - { - //vec2 old_pos = pos; - float fraction = 1.0f/(float)(max+1); - for(int i = 0; i <= max; i++) - { - //float amount = i/(float)max; - //if(max == 0) - //amount = 0; - - vec2 new_pos = pos + vel*fraction; // TODO: this row is not nice - - if(test_box(vec2(new_pos.x, new_pos.y), size)) - { - int hits = 0; - - if(test_box(vec2(pos.x, new_pos.y), size)) - { - new_pos.y = pos.y; - vel.y *= -elasticity; - hits++; - } - - if(test_box(vec2(new_pos.x, pos.y), size)) - { - new_pos.x = pos.x; - vel.x *= -elasticity; - hits++; - } - - // neither of the tests got a collision. - // this is a real _corner case_! - if(hits == 0) - { - new_pos.y = pos.y; - vel.y *= -elasticity; - new_pos.x = pos.x; - vel.x *= -elasticity; - } - } - - pos = new_pos; - } - } - - *inout_pos = pos; - *inout_vel = vel; + return 2*v*v*v - 3*v*v+1; } -float hermite_basis1(float v) +float VelocityRamp(float Value, float Start, float Range, float Curvature) { - return 2*v*v*v - 3*v*v+1; + if(Value < Start) + return 1.0f; + return 1.0f/powf(Curvature, (Value-Start)/Range); } -float velocity_ramp(float value, float start, float range, float curvature) +void CCharacterCore::Init(CWorldCore *pWorld, CCollision *pCollision) { - if(value < start) - return 1.0f; - return 1.0f/pow(curvature, (value-start)/range); + m_pWorld = pWorld; + m_pCollision = pCollision; } -void CHARACTER_CORE::reset() +void CCharacterCore::Reset() { - pos = vec2(0,0); - vel = vec2(0,0); - hook_pos = vec2(0,0); - hook_dir = vec2(0,0); - hook_tick = 0; - hook_state = HOOK_IDLE; - hooked_player = -1; - jumped = 0; - triggered_events = 0; + m_Pos = vec2(0,0); + m_Vel = vec2(0,0); + m_HookPos = vec2(0,0); + m_HookDir = vec2(0,0); + m_HookTick = 0; + m_HookState = HOOK_IDLE; + m_HookedPlayer = -1; + m_Jumped = 0; + m_TriggeredEvents = 0; } -void CHARACTER_CORE::tick(bool use_input) +void CCharacterCore::Tick(bool UseInput) { - float phys_size = 28.0f; - triggered_events = 0; + float PhysSize = 28.0f; + m_TriggeredEvents = 0; // get ground state - bool grounded = false; - if(col_check_point(pos.x+phys_size/2, pos.y+phys_size/2+5)) - grounded = true; - if(col_check_point(pos.x-phys_size/2, pos.y+phys_size/2+5)) - grounded = true; + bool Grounded = false; + if(m_pCollision->CheckPoint(m_Pos.x+PhysSize/2, m_Pos.y+PhysSize/2+5)) + Grounded = true; + if(m_pCollision->CheckPoint(m_Pos.x-PhysSize/2, m_Pos.y+PhysSize/2+5)) + Grounded = true; - vec2 target_direction = normalize(vec2(input.target_x, input.target_y)); + vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY)); - vel.y += world->tuning.gravity; + m_Vel.y += m_pWorld->m_Tuning.m_Gravity; - float max_speed = grounded ? world->tuning.ground_control_speed : world->tuning.air_control_speed; - float accel = grounded ? world->tuning.ground_control_accel : world->tuning.air_control_accel; - float friction = grounded ? world->tuning.ground_friction : world->tuning.air_friction; + float MaxSpeed = Grounded ? m_pWorld->m_Tuning.m_GroundControlSpeed : m_pWorld->m_Tuning.m_AirControlSpeed; + float Accel = Grounded ? m_pWorld->m_Tuning.m_GroundControlAccel : m_pWorld->m_Tuning.m_AirControlAccel; + float Friction = Grounded ? m_pWorld->m_Tuning.m_GroundFriction : m_pWorld->m_Tuning.m_AirFriction; // handle input - if(use_input) + if(UseInput) { - direction = input.direction; + m_Direction = m_Input.m_Direction; // setup angle float a = 0; - if(input.target_x == 0) - a = atan((float)input.target_y); + if(m_Input.m_TargetX == 0) + a = atanf((float)m_Input.m_TargetY); else - a = atan((float)input.target_y/(float)input.target_x); + a = atanf((float)m_Input.m_TargetY/(float)m_Input.m_TargetX); - if(input.target_x < 0) + if(m_Input.m_TargetX < 0) a = a+pi; - angle = (int)(a*256.0f); + m_Angle = (int)(a*256.0f); // handle jump - if(input.jump) + if(m_Input.m_Jump) { - if(!(jumped&1)) + if(!(m_Jumped&1)) { - if(grounded) + if(Grounded) { - triggered_events |= COREEVENT_GROUND_JUMP; - vel.y = -world->tuning.ground_jump_impulse; - jumped |= 1; + m_TriggeredEvents |= COREEVENT_GROUND_JUMP; + m_Vel.y = -m_pWorld->m_Tuning.m_GroundJumpImpulse; + m_Jumped |= 1; } - else if(!(jumped&2)) + else if(!(m_Jumped&2)) { - triggered_events |= COREEVENT_AIR_JUMP; - vel.y = -world->tuning.air_jump_impulse; - jumped |= 3; + m_TriggeredEvents |= COREEVENT_AIR_JUMP; + m_Vel.y = -m_pWorld->m_Tuning.m_AirJumpImpulse; + m_Jumped |= 3; } } } else - jumped &= ~1; + m_Jumped &= ~1; // handle hook - if(input.hook) + if(m_Input.m_Hook) { - if(hook_state == HOOK_IDLE) + if(m_HookState == HOOK_IDLE) { - hook_state = HOOK_FLYING; - hook_pos = pos+target_direction*phys_size*1.5f; - hook_dir = target_direction; - hooked_player = -1; - hook_tick = 0; - triggered_events |= COREEVENT_HOOK_LAUNCH; + m_HookState = HOOK_FLYING; + m_HookPos = m_Pos+TargetDirection*PhysSize*1.5f; + m_HookDir = TargetDirection; + m_HookedPlayer = -1; + m_HookTick = 0; + m_TriggeredEvents |= COREEVENT_HOOK_LAUNCH; } } else { - hooked_player = -1; - hook_state = HOOK_IDLE; - hook_pos = pos; + m_HookedPlayer = -1; + m_HookState = HOOK_IDLE; + m_HookPos = m_Pos; } } // add the speed modification according to players wanted direction - if(direction < 0) - vel.x = saturated_add(-max_speed, max_speed, vel.x, -accel); - if(direction > 0) - vel.x = saturated_add(-max_speed, max_speed, vel.x, accel); - if(direction == 0) - vel.x *= friction; + if(m_Direction < 0) + m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, -Accel); + if(m_Direction > 0) + m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, Accel); + if(m_Direction == 0) + m_Vel.x *= Friction; // handle jumping // 1 bit = to keep track if a jump has been made on this input // 2 bit = to keep track if a air-jump has been made - if(grounded) - jumped &= ~2; + if(Grounded) + m_Jumped &= ~2; // do hook - if(hook_state == HOOK_IDLE) + if(m_HookState == HOOK_IDLE) { - hooked_player = -1; - hook_state = HOOK_IDLE; - hook_pos = pos; + m_HookedPlayer = -1; + m_HookState = HOOK_IDLE; + m_HookPos = m_Pos; } - else if(hook_state >= HOOK_RETRACT_START && hook_state < HOOK_RETRACT_END) + else if(m_HookState >= HOOK_RETRACT_START && m_HookState < HOOK_RETRACT_END) { - hook_state++; + m_HookState++; } - else if(hook_state == HOOK_RETRACT_END) + else if(m_HookState == HOOK_RETRACT_END) { - hook_state = HOOK_RETRACTED; - triggered_events |= COREEVENT_HOOK_RETRACT; - hook_state = HOOK_RETRACTED; + m_HookState = HOOK_RETRACTED; + m_TriggeredEvents |= COREEVENT_HOOK_RETRACT; + m_HookState = HOOK_RETRACTED; } - else if(hook_state == HOOK_FLYING) + else if(m_HookState == HOOK_FLYING) { - vec2 new_pos = hook_pos+hook_dir*world->tuning.hook_fire_speed; - if(distance(pos, new_pos) > world->tuning.hook_length) + vec2 NewPos = m_HookPos+m_HookDir*m_pWorld->m_Tuning.m_HookFireSpeed; + if(distance(m_Pos, NewPos) > m_pWorld->m_Tuning.m_HookLength) { - hook_state = HOOK_RETRACT_START; - new_pos = pos + normalize(new_pos-pos) * world->tuning.hook_length; + m_HookState = HOOK_RETRACT_START; + NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength; } // make sure that the hook doesn't go though the ground - bool going_to_hit_ground = false; - bool going_to_retract = false; - int hit = col_intersect_line(hook_pos, new_pos, &new_pos, 0); - if(hit) + bool GoingToHitGround = false; + bool GoingToRetract = false; + int Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0); + if(Hit) { - if(hit&COLFLAG_NOHOOK) - going_to_retract = true; + if(Hit&CCollision::COLFLAG_NOHOOK) + GoingToRetract = true; else - going_to_hit_ground = true; + GoingToHitGround = true; } // Check against other players first - if(world && world->tuning.player_hooking) + if(m_pWorld && m_pWorld->m_Tuning.m_PlayerHooking) { - float dist = 0.0f; + float Dist = 0.0f; for(int i = 0; i < MAX_CLIENTS; i++) { - CHARACTER_CORE *p = world->characters[i]; + CCharacterCore *p = m_pWorld->m_apCharacters[i]; if(!p || p == this) continue; - vec2 closest_point = closest_point_on_line(hook_pos, new_pos, p->pos); - if(distance(p->pos, closest_point) < phys_size+2.0f) + vec2 ClosestPoint = closest_point_on_line(m_HookPos, NewPos, p->m_Pos); + if(distance(p->m_Pos, ClosestPoint) < PhysSize+2.0f) { - if (hooked_player == -1 || distance (hook_pos, p->pos) < dist) + if (m_HookedPlayer == -1 || distance(m_HookPos, p->m_Pos) < Dist) { - triggered_events |= COREEVENT_HOOK_ATTACH_PLAYER; - hook_state = HOOK_GRABBED; - hooked_player = i; - dist = distance (hook_pos, p->pos); + m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER; + m_HookState = HOOK_GRABBED; + m_HookedPlayer = i; + Dist = distance(m_HookPos, p->m_Pos); } } } } - if(hook_state == HOOK_FLYING) + if(m_HookState == HOOK_FLYING) { // check against ground - if(going_to_hit_ground) + if(GoingToHitGround) { - triggered_events |= COREEVENT_HOOK_ATTACH_GROUND; - hook_state = HOOK_GRABBED; + m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_GROUND; + m_HookState = HOOK_GRABBED; } - else if(going_to_retract) + else if(GoingToRetract) { - triggered_events |= COREEVENT_HOOK_HIT_NOHOOK; - hook_state = HOOK_RETRACT_START; + m_TriggeredEvents |= COREEVENT_HOOK_HIT_NOHOOK; + m_HookState = HOOK_RETRACT_START; } - hook_pos = new_pos; + m_HookPos = NewPos; } } - if(hook_state == HOOK_GRABBED) + if(m_HookState == HOOK_GRABBED) { - if(hooked_player != -1) + if(m_HookedPlayer != -1) { - CHARACTER_CORE *p = world->characters[hooked_player]; + CCharacterCore *p = m_pWorld->m_apCharacters[m_HookedPlayer]; if(p) - hook_pos = p->pos; + m_HookPos = p->m_Pos; else { // release hook - hooked_player = -1; - hook_state = HOOK_RETRACTED; - hook_pos = pos; + m_HookedPlayer = -1; + m_HookState = HOOK_RETRACTED; + m_HookPos = m_Pos; } // keep players hooked for a max of 1.5sec - //if(server_tick() > hook_tick+(server_tickspeed()*3)/2) + //if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2) //release_hooked(); } // don't do this hook rutine when we are hook to a player - if(hooked_player == -1 && distance(hook_pos, pos) > 46.0f) + if(m_HookedPlayer == -1 && distance(m_HookPos, m_Pos) > 46.0f) { - vec2 hookvel = normalize(hook_pos-pos)*world->tuning.hook_drag_accel; + vec2 HookVel = normalize(m_HookPos-m_Pos)*m_pWorld->m_Tuning.m_HookDragAccel; // the hook as more power to drag you up then down. // this makes it easier to get on top of an platform - if(hookvel.y > 0) - hookvel.y *= 0.3f; + if(HookVel.y > 0) + HookVel.y *= 0.3f; // the hook will boost it's power if the player wants to move // in that direction. otherwise it will dampen everything abit - if((hookvel.x < 0 && direction < 0) || (hookvel.x > 0 && direction > 0)) - hookvel.x *= 0.95f; + if((HookVel.x < 0 && m_Direction < 0) || (HookVel.x > 0 && m_Direction > 0)) + HookVel.x *= 0.95f; else - hookvel.x *= 0.75f; + HookVel.x *= 0.75f; - vec2 new_vel = vel+hookvel; + vec2 NewVel = m_Vel+HookVel; // check if we are under the legal limit for the hook - if(length(new_vel) < world->tuning.hook_drag_speed || length(new_vel) < length(vel)) - vel = new_vel; // no problem. apply + if(length(NewVel) < m_pWorld->m_Tuning.m_HookDragSpeed || length(NewVel) < length(m_Vel)) + m_Vel = NewVel; // no problem. apply } // release hook (max hook time is 1.25 - hook_tick++; - if(hooked_player != -1 && (hook_tick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !world->characters[hooked_player])) + m_HookTick++; + if(m_HookedPlayer != -1 && (m_HookTick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !m_pWorld->m_apCharacters[m_HookedPlayer])) { - hooked_player = -1; - hook_state = HOOK_RETRACTED; - hook_pos = pos; + m_HookedPlayer = -1; + m_HookState = HOOK_RETRACTED; + m_HookPos = m_Pos; } } - if(world && world->tuning.player_collision) + if(m_pWorld && m_pWorld->m_Tuning.m_PlayerCollision) { for(int i = 0; i < MAX_CLIENTS; i++) { - CHARACTER_CORE *p = world->characters[i]; + CCharacterCore *p = m_pWorld->m_apCharacters[i]; if(!p) continue; @@ -420,95 +314,95 @@ void CHARACTER_CORE::tick(bool use_input) continue; // make sure that we don't nudge our self // handle player <-> player collision - float d = distance(pos, p->pos); - vec2 dir = normalize(pos - p->pos); - if(d < phys_size*1.25f && d > 1.0f) + float d = distance(m_Pos, p->m_Pos); + vec2 Dir = normalize(m_Pos - p->m_Pos); + if(d < PhysSize*1.25f && d > 1.0f) { - float a = (phys_size*1.45f - d); + float a = (PhysSize*1.45f - d); // make sure that we don't add excess force by checking the // direction against the current velocity - vec2 veldir = normalize(vel); - float v = 1-(dot(veldir, dir)+1)/2; - vel = vel + dir*a*(v*0.75f); - vel = vel * 0.85f; + vec2 VelDir = normalize(m_Vel); + float v = 1-(dot(VelDir, Dir)+1)/2; + m_Vel = m_Vel + Dir*a*(v*0.75f); + m_Vel = m_Vel * 0.85f; } // handle hook influence - if(hooked_player == i) + if(m_HookedPlayer == i) { - if(d > phys_size*1.50f) // TODO: fix tweakable variable + if(d > PhysSize*1.50f) // TODO: fix tweakable variable { - float accel = world->tuning.hook_drag_accel * (d/world->tuning.hook_length); - float drag_speed = world->tuning.hook_drag_speed; + float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (d/m_pWorld->m_Tuning.m_HookLength); + float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; // add force to the hooked player - p->vel.x = saturated_add(-drag_speed, drag_speed, p->vel.x, accel*dir.x*1.5f); - p->vel.y = saturated_add(-drag_speed, drag_speed, p->vel.y, accel*dir.y*1.5f); + p->m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, p->m_Vel.x, Accel*Dir.x*1.5f); + p->m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, p->m_Vel.y, Accel*Dir.y*1.5f); // add a little bit force to the guy who has the grip - vel.x = saturated_add(-drag_speed, drag_speed, vel.x, -accel*dir.x*0.25f); - vel.y = saturated_add(-drag_speed, drag_speed, vel.y, -accel*dir.y*0.25f); + m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -Accel*Dir.x*0.25f); + m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -Accel*Dir.y*0.25f); } } } } // clamp the velocity to something sane - if(length(vel) > 6000) - vel = normalize(vel) * 6000; + if(length(m_Vel) > 6000) + m_Vel = normalize(m_Vel) * 6000; } -void CHARACTER_CORE::move() +void CCharacterCore::Move() { - float rampvalue = velocity_ramp(length(vel)*50, world->tuning.velramp_start, world->tuning.velramp_range, world->tuning.velramp_curvature); + float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); - vel.x = vel.x*rampvalue; - move_box(&pos, &vel, vec2(28.0f, 28.0f), 0); - vel.x = vel.x*(1.0f/rampvalue); + m_Vel.x = m_Vel.x*RampValue; + m_pCollision->MoveBox(&m_Pos, &m_Vel, vec2(28.0f, 28.0f), 0); + m_Vel.x = m_Vel.x*(1.0f/RampValue); } -void CHARACTER_CORE::write(NETOBJ_CHARACTER_CORE *obj_core) +void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore) { - obj_core->x = round(pos.x); - obj_core->y = round(pos.y); + pObjCore->m_X = round(m_Pos.x); + pObjCore->m_Y = round(m_Pos.y); - obj_core->vx = round(vel.x*256.0f); - obj_core->vy = round(vel.y*256.0f); - obj_core->hook_state = hook_state; - obj_core->hook_tick = hook_tick; - obj_core->hook_x = round(hook_pos.x); - obj_core->hook_y = round(hook_pos.y); - obj_core->hook_dx = round(hook_dir.x*256.0f); - obj_core->hook_dy = round(hook_dir.y*256.0f); - obj_core->hooked_player = hooked_player; - obj_core->jumped = jumped; - obj_core->direction = direction; - obj_core->angle = angle; + pObjCore->m_VelX = round(m_Vel.x*256.0f); + pObjCore->m_VelY = round(m_Vel.y*256.0f); + pObjCore->m_HookState = m_HookState; + pObjCore->m_HookTick = m_HookTick; + pObjCore->m_HookX = round(m_HookPos.x); + pObjCore->m_HookY = round(m_HookPos.y); + pObjCore->m_HookDx = round(m_HookDir.x*256.0f); + pObjCore->m_HookDy = round(m_HookDir.y*256.0f); + pObjCore->m_HookedPlayer = m_HookedPlayer; + pObjCore->m_Jumped = m_Jumped; + pObjCore->m_Direction = m_Direction; + pObjCore->m_Angle = m_Angle; } -void CHARACTER_CORE::read(const NETOBJ_CHARACTER_CORE *obj_core) +void CCharacterCore::Read(const CNetObj_CharacterCore *pObjCore) { - pos.x = obj_core->x; - pos.y = obj_core->y; - vel.x = obj_core->vx/256.0f; - vel.y = obj_core->vy/256.0f; - hook_state = obj_core->hook_state; - hook_tick = obj_core->hook_tick; - hook_pos.x = obj_core->hook_x; - hook_pos.y = obj_core->hook_y; - hook_dir.x = obj_core->hook_dx/256.0f; - hook_dir.y = obj_core->hook_dy/256.0f; - hooked_player = obj_core->hooked_player; - jumped = obj_core->jumped; - direction = obj_core->direction; - angle = obj_core->angle; + m_Pos.x = pObjCore->m_X; + m_Pos.y = pObjCore->m_Y; + m_Vel.x = pObjCore->m_VelX/256.0f; + m_Vel.y = pObjCore->m_VelY/256.0f; + m_HookState = pObjCore->m_HookState; + m_HookTick = pObjCore->m_HookTick; + m_HookPos.x = pObjCore->m_HookX; + m_HookPos.y = pObjCore->m_HookY; + m_HookDir.x = pObjCore->m_HookDx/256.0f; + m_HookDir.y = pObjCore->m_HookDy/256.0f; + m_HookedPlayer = pObjCore->m_HookedPlayer; + m_Jumped = pObjCore->m_Jumped; + m_Direction = pObjCore->m_Direction; + m_Angle = pObjCore->m_Angle; } -void CHARACTER_CORE::quantize() +void CCharacterCore::Quantize() { - NETOBJ_CHARACTER_CORE c; - write(&c); - read(&c); + CNetObj_CharacterCore Core; + Write(&Core); + Read(&Core); } diff --git a/src/game/gamecore.h b/src/game/gamecore.h new file mode 100644 index 00000000..816e1771 --- /dev/null +++ b/src/game/gamecore.h @@ -0,0 +1,205 @@ +#ifndef GAME_GAMECORE_H +#define GAME_GAMECORE_H + +#include <base/system.h> +#include <base/math.h> + +#include <math.h> +#include "collision.h" +#include <engine/shared/protocol.h> +#include <game/generated/protocol.h> + + +class CTuneParam +{ + int m_Value; +public: + void Set(int v) { m_Value = v; } + int Get() const { return m_Value; } + CTuneParam &operator = (int v) { m_Value = (int)(v*100.0f); return *this; } + CTuneParam &operator = (float v) { m_Value = (int)(v*100.0f); return *this; } + operator float() const { return m_Value/100.0f; } +}; + +class CTuningParams +{ +public: + CTuningParams() + { + const float TicksPerSecond = 50.0f; + #define MACRO_TUNING_PARAM(Name,ScriptName,Value) m_##Name.Set((int)(Value*100.0f)); + #include "tuning.h" + #undef MACRO_TUNING_PARAM + } + + static const char *m_apNames[]; + + #define MACRO_TUNING_PARAM(Name,ScriptName,Value) CTuneParam m_##Name; + #include "tuning.h" + #undef MACRO_TUNING_PARAM + + static int Num() { return sizeof(CTuningParams)/sizeof(int); } + bool Set(int Index, float Value); + bool Set(const char *pName, float Value); + bool Get(int Index, float *pValue); + bool Get(const char *pName, float *pValue); +}; + + +inline vec2 GetDirection(int Angle) +{ + float a = Angle/256.0f; + return vec2(cosf(a), sinf(a)); +} + +inline vec2 GetDir(float a) +{ + return vec2(cosf(a), sinf(a)); +} + +inline float GetAngle(vec2 Dir) +{ + if(Dir.x == 0 && Dir.y == 0) + return 0.0f; + float a = atanf(Dir.y/Dir.x); + if(Dir.x < 0) + a = a+pi; + return a; +} + +inline void StrToInts(int *pInts, int Num, const char *pStr) +{ + int Index = 0; + while(Num) + { + char aBuf[4] = {0,0,0,0}; + for(int c = 0; c < 4 && pStr[Index]; c++, Index++) + aBuf[c] = pStr[Index]; + *pInts = ((aBuf[0]+128)<<24)|((aBuf[1]+128)<<16)|((aBuf[2]+128)<<8)|(aBuf[3]+128); + pInts++; + Num--; + } + + // null terminate + pInts[-1] &= 0xffffff00; +} + +inline void IntsToStr(const int *pInts, int Num, char *pStr) +{ + while(Num) + { + pStr[0] = (((*pInts)>>24)&0xff)-128; + pStr[1] = (((*pInts)>>16)&0xff)-128; + pStr[2] = (((*pInts)>>8)&0xff)-128; + pStr[3] = ((*pInts)&0xff)-128; + pStr += 4; + pInts++; + Num--; + } + + // null terminate + pStr[-1] = 0; +} + + + +inline vec2 CalcPos(vec2 p, vec2 v, float Curvature, float Speed, float t) +{ + vec2 n; + t *= Speed; + n.x = p.x + v.x*t; + n.y = p.y + v.y*t + Curvature/10000*(t*t); + return n; +} + + +template<typename T> +inline T SaturatedAdd(T Min, T Max, T Current, T Modifier) +{ + if(Modifier < 0) + { + if(Current < Min) + return Current; + Current += Modifier; + if(Current < Min) + Current = Min; + return Current; + } + else + { + if(Current > Max) + return Current; + Current += Modifier; + if(Current > Max) + Current = Max; + return Current; + } +} + + +float VelocityRamp(float Value, float Start, float Range, float Curvature); + +// hooking stuff +enum +{ + HOOK_RETRACTED=-1, + HOOK_IDLE=0, + HOOK_RETRACT_START=1, + HOOK_RETRACT_END=3, + HOOK_FLYING, + HOOK_GRABBED, + + COREEVENT_GROUND_JUMP=0x01, + COREEVENT_AIR_JUMP=0x02, + COREEVENT_HOOK_LAUNCH=0x04, + COREEVENT_HOOK_ATTACH_PLAYER=0x08, + COREEVENT_HOOK_ATTACH_GROUND=0x10, + COREEVENT_HOOK_HIT_NOHOOK=0x20, + COREEVENT_HOOK_RETRACT=0x40, +}; + +class CWorldCore +{ +public: + CWorldCore() + { + mem_zero(m_apCharacters, sizeof(m_apCharacters)); + } + + CTuningParams m_Tuning; + class CCharacterCore *m_apCharacters[MAX_CLIENTS]; +}; + +class CCharacterCore +{ + CWorldCore *m_pWorld; + CCollision *m_pCollision; +public: + vec2 m_Pos; + vec2 m_Vel; + + vec2 m_HookPos; + vec2 m_HookDir; + int m_HookTick; + int m_HookState; + int m_HookedPlayer; + + int m_Jumped; + + int m_Direction; + int m_Angle; + CNetObj_PlayerInput m_Input; + + int m_TriggeredEvents; + + void Init(CWorldCore *pWorld, CCollision *pCollision); + void Reset(); + void Tick(bool UseInput); + void Move(); + + void Read(const CNetObj_CharacterCore *pObjCore); + void Write(CNetObj_CharacterCore *pObjCore); + void Quantize(); +}; + +#endif diff --git a/src/game/gamecore.hpp b/src/game/gamecore.hpp deleted file mode 100644 index 2734820c..00000000 --- a/src/game/gamecore.hpp +++ /dev/null @@ -1,200 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#ifndef GAME_GAME_H -#define GAME_GAME_H - -#include <base/system.h> -#include <base/math.hpp> - -#include <engine/e_common_interface.h> -#include <math.h> -#include "collision.hpp" -#include <game/generated/g_protocol.hpp> - -struct TUNING_PARAMS -{ - TUNING_PARAMS() - { - const float ticks_per_second = 50.0f; - #define MACRO_TUNING_PARAM(name,value) name.set((int)(value*100.0f)); - #include "tuning.hpp" - #undef MACRO_TUNING_PARAM - } - - static const char *names[]; - - #define MACRO_TUNING_PARAM(name,value) tune_param name; - #include "tuning.hpp" - #undef MACRO_TUNING_PARAM - - static int num() { return sizeof(TUNING_PARAMS)/sizeof(int); } - bool set(int index, float value); - bool set(const char *name, float value); - bool get(int index, float *value); - bool get(const char *name, float *value); -}; - - -inline vec2 get_direction(int angle) -{ - float a = angle/256.0f; - return vec2(cosf(a), sinf(a)); -} - -inline vec2 get_dir(float a) -{ - return vec2(cosf(a), sinf(a)); -} - -inline float get_angle(vec2 dir) -{ - float a = atan(dir.y/dir.x); - if(dir.x < 0) - a = a+pi; - return a; -} - -inline void str_to_ints(int *ints, int num, const char *str) -{ - int index = 0; - while(num) - { - char buf[4] = {0,0,0,0}; - for(int c = 0; c < 4 && str[index]; c++, index++) - buf[c] = str[index]; - *ints = ((buf[0]+128)<<24)|((buf[1]+128)<<16)|((buf[2]+128)<<8)|(buf[3]+128); - ints++; - num--; - } - - // null terminate - ints[-1] &= 0xffffff00; -} - -inline void ints_to_str(const int *ints, int num, char *str) -{ - while(num) - { - str[0] = (((*ints)>>24)&0xff)-128; - str[1] = (((*ints)>>16)&0xff)-128; - str[2] = (((*ints)>>8)&0xff)-128; - str[3] = ((*ints)&0xff)-128; - str += 4; - ints++; - num--; - } - - // null terminate - str[-1] = 0; -} - - - -inline vec2 calc_pos(vec2 p, vec2 v, float curvature, float speed, float t) -{ - vec2 n; - t *= speed; - n.x = p.x + v.x*t; - n.y = p.y + v.y*t + curvature/10000*(t*t); - return n; -} - - -template<typename T> -inline T saturated_add(T min, T max, T current, T modifier) -{ - if(modifier < 0) - { - if(current < min) - return current; - current += modifier; - if(current < min) - current = min; - return current; - } - else - { - if(current > max) - return current; - current += modifier; - if(current > max) - current = max; - return current; - } -} - -void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces); -void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity); -bool test_box(vec2 pos, vec2 size); -float velocity_ramp(float value, float start, float range, float curvature); - -// hooking stuff -enum -{ - HOOK_RETRACTED=-1, - HOOK_IDLE=0, - HOOK_RETRACT_START=1, - HOOK_RETRACT_END=3, - HOOK_FLYING, - HOOK_GRABBED, - - COREEVENT_GROUND_JUMP=0x01, - COREEVENT_AIR_JUMP=0x02, - COREEVENT_HOOK_LAUNCH=0x04, - COREEVENT_HOOK_ATTACH_PLAYER=0x08, - COREEVENT_HOOK_ATTACH_GROUND=0x10, - COREEVENT_HOOK_HIT_NOHOOK=0x20, - COREEVENT_HOOK_RETRACT=0x40, -}; - -class WORLD_CORE -{ -public: - WORLD_CORE() - { - mem_zero(characters, sizeof(characters)); - } - - TUNING_PARAMS tuning; - class CHARACTER_CORE *characters[MAX_CLIENTS]; -}; - -class CHARACTER_CORE -{ -public: - WORLD_CORE *world; - - vec2 pos; - vec2 vel; - - vec2 hook_pos; - vec2 hook_dir; - int hook_tick; - int hook_state; - int hooked_player; - - int jumped; - - int direction; - int angle; - NETOBJ_PLAYER_INPUT input; - - int triggered_events; - - void reset(); - void tick(bool use_input); - void move(); - - void read(const NETOBJ_CHARACTER_CORE *obj_core); - void write(NETOBJ_CHARACTER_CORE *obj_core); - void quantize(); -}; - - -#define LERP(a,b,t) (a + (b-a) * t) -#define min(a, b) ( a > b ? b : a) -#define max(a, b) ( a > b ? a : b) - -inline bool col_check_point(float x, float y) { return col_is_solid(round(x), round(y)) != 0; } -inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); } - -#endif diff --git a/src/game/layers.cpp b/src/game/layers.cpp index 832dc766..e99befd2 100644 --- a/src/game/layers.cpp +++ b/src/game/layers.cpp @@ -1,57 +1,61 @@ -#include <engine/e_common_interface.h> -#include "layers.hpp" +#include "layers.h" -static MAPITEM_LAYER_TILEMAP *game_layer = 0; -static MAPITEM_GROUP *game_group = 0; - -static int groups_start = 0; -static int groups_num = 0; -static int layers_start = 0; -static int layers_num = 0; +CLayers::CLayers() +{ + m_GroupsNum = 0; + m_GroupsStart = 0; + m_LayersNum = 0; + m_LayersStart = 0; + m_pGameGroup = 0; + m_pGameLayer = 0; + m_pMap = 0; +} -void layers_init() +void CLayers::Init(class IKernel *pKernel) { - map_get_type(MAPITEMTYPE_GROUP, &groups_start, &groups_num); - map_get_type(MAPITEMTYPE_LAYER, &layers_start, &layers_num); + m_pMap = pKernel->RequestInterface<IMap>(); + m_pMap->GetType(MAPITEMTYPE_GROUP, &m_GroupsStart, &m_GroupsNum); + m_pMap->GetType(MAPITEMTYPE_LAYER, &m_LayersStart, &m_LayersNum); - for(int g = 0; g < layers_num_groups(); g++) + for(int g = 0; g < NumGroups(); g++) { - MAPITEM_GROUP *group = layers_get_group(g); - for(int l = 0; l < group->num_layers; l++) + CMapItemGroup *pGroup = GetGroup(g); + for(int l = 0; l < pGroup->m_NumLayers; l++) { - MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l); + CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l); - if(layer->type == LAYERTYPE_TILES) + if(pLayer->m_Type == LAYERTYPE_TILES) { - MAPITEM_LAYER_TILEMAP *tilemap = (MAPITEM_LAYER_TILEMAP *)layer; - if(tilemap->flags&1) + CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer); + if(pTilemap->m_Flags&1) { - game_layer = tilemap; - game_group = group; + m_pGameLayer = pTilemap; + m_pGameGroup = pGroup; + + // make sure the game group has standard settings + m_pGameGroup->m_OffsetX = 0; + m_pGameGroup->m_OffsetY = 0; + m_pGameGroup->m_ParallaxX = 100; + m_pGameGroup->m_ParallaxY = 100; + m_pGameGroup->m_UseClipping = 0; + m_pGameGroup->m_ClipX = 0; + m_pGameGroup->m_ClipY = 0; + m_pGameGroup->m_ClipW = 0; + m_pGameGroup->m_ClipH = 0; + + break; } } } } } -int layers_num_groups() { return groups_num; } -MAPITEM_GROUP *layers_get_group(int index) -{ - return (MAPITEM_GROUP *)map_get_item(groups_start+index, 0, 0); -} - -MAPITEM_LAYER *layers_get_layer(int index) +CMapItemGroup *CLayers::GetGroup(int Index) const { - return (MAPITEM_LAYER *)map_get_item(layers_start+index, 0, 0); + return static_cast<CMapItemGroup *>(m_pMap->GetItem(m_GroupsStart+Index, 0, 0)); } -MAPITEM_LAYER_TILEMAP *layers_game_layer() +CMapItemLayer *CLayers::GetLayer(int Index) const { - return game_layer; + return static_cast<CMapItemLayer *>(m_pMap->GetItem(m_LayersStart+Index, 0, 0)); } - -MAPITEM_GROUP *layers_game_group() -{ - return game_group; -} - diff --git a/src/game/layers.h b/src/game/layers.h new file mode 100644 index 00000000..198fe695 --- /dev/null +++ b/src/game/layers.h @@ -0,0 +1,28 @@ +#ifndef GAME_LAYERS_H +#define GAME_LAYERS_H + +#include <engine/map.h> +#include <game/mapitems.h> + +class CLayers +{ + int m_GroupsNum; + int m_GroupsStart; + int m_LayersNum; + int m_LayersStart; + CMapItemGroup *m_pGameGroup; + CMapItemLayerTilemap *m_pGameLayer; + class IMap *m_pMap; + +public: + CLayers(); + void Init(class IKernel *pKernel); + int NumGroups() const { return m_GroupsNum; }; + class IMap *Map() const { return m_pMap; }; + CMapItemGroup *GameGroup() const { return m_pGameGroup; }; + CMapItemLayerTilemap *GameLayer() const { return m_pGameLayer; }; + CMapItemGroup *GetGroup(int Index) const; + CMapItemLayer *GetLayer(int Index) const; +}; + +#endif diff --git a/src/game/layers.hpp b/src/game/layers.hpp deleted file mode 100644 index cb18419b..00000000 --- a/src/game/layers.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "mapitems.hpp" - -void layers_init(); - -MAPITEM_LAYER_TILEMAP *layers_game_layer(); -MAPITEM_GROUP *layers_game_group(); - -int layers_num_groups(); -MAPITEM_GROUP *layers_get_group(int index); -MAPITEM_LAYER *layers_get_layer(int index); - - diff --git a/src/game/localization.cpp b/src/game/localization.cpp index 3a1b0411..02065e36 100644 --- a/src/game/localization.cpp +++ b/src/game/localization.cpp @@ -1,100 +1,101 @@ -#include "localization.hpp" -#include <base/tl/algorithm.hpp> +#include "localization.h" +#include <base/tl/algorithm.h> -#include <engine/e_linereader.h> +#include <engine/shared/linereader.h> -const char *localize(const char *str) +const char *Localize(const char *pStr) { - const char *new_str = localization.find_string(str_quickhash(str)); - return new_str ? new_str : str; + const char *pNewStr = g_Localization.FindString(str_quickhash(pStr)); + return pNewStr ? pNewStr : pStr; } -LOC_CONSTSTRING::LOC_CONSTSTRING(const char *str) +CLocConstString::CLocConstString(const char *pStr) { - default_str = str; - hash = str_quickhash(default_str); - version = -1; + m_pDefaultStr = pStr; + m_Hash = str_quickhash(m_pDefaultStr); + m_Version = -1; } -void LOC_CONSTSTRING::reload() +void CLocConstString::Reload() { - version = localization.version(); - const char *new_str = localization.find_string(hash); - current_str = new_str; - if(!current_str) - current_str = default_str; + m_Version = g_Localization.Version(); + const char *pNewStr = g_Localization.FindString(m_Hash); + m_pCurrentStr = pNewStr; + if(!m_pCurrentStr) + m_pCurrentStr = m_pDefaultStr; } -LOCALIZATIONDATABASE::LOCALIZATIONDATABASE() +CLocalizationDatabase::CLocalizationDatabase() { - current_version = 0; + m_CurrentVersion = 0; } -void LOCALIZATIONDATABASE::add_string(const char *org_str, const char *new_str) +void CLocalizationDatabase::AddString(const char *pOrgStr, const char *pNewStr) { - STRING s; - s.hash = str_quickhash(org_str); - s.replacement = new_str; - strings.add(s); + CString s; + s.m_Hash = str_quickhash(pOrgStr); + s.m_Replacement = pNewStr; + m_Strings.add(s); } -bool LOCALIZATIONDATABASE::load(const char *filename) +bool CLocalizationDatabase::Load(const char *pFilename) { // empty string means unload - if(filename[0] == 0) + if(pFilename[0] == 0) { - strings.clear(); + m_Strings.clear(); + m_CurrentVersion = 0; return true; } - LINEREADER lr; - IOHANDLE io = io_open(filename, IOFLAG_READ); - if(!io) + IOHANDLE IoHandle = io_open(pFilename, IOFLAG_READ); + if(!IoHandle) return false; - dbg_msg("localization", "loaded '%s'", filename); - strings.clear(); + dbg_msg("localization", "loaded '%s'", pFilename); + m_Strings.clear(); - linereader_init(&lr, io); - char *line; - while((line = linereader_get(&lr))) + CLineReader LineReader; + LineReader.Init(IoHandle); + char *pLine; + while((pLine = LineReader.Get())) { - if(!str_length(line)) + if(!str_length(pLine)) continue; - if(line[0] == '#') // skip comments + if(pLine[0] == '#') // skip comments continue; - char *replacement = linereader_get(&lr); - if(!replacement) + char *pReplacement = LineReader.Get(); + if(!pReplacement) { dbg_msg("", "unexpected end of file"); break; } - if(replacement[0] != '=' || replacement[1] != '=' || replacement[2] != ' ') + if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ') { - dbg_msg("", "malform replacement line for '%s'", line); + dbg_msg("", "malform replacement line for '%s'", pLine); continue; } - replacement += 3; - localization.add_string(line, replacement); + pReplacement += 3; + AddString(pLine, pReplacement); } - current_version++; + m_CurrentVersion++; return true; } -const char *LOCALIZATIONDATABASE::find_string(unsigned hash) +const char *CLocalizationDatabase::FindString(unsigned Hash) { - STRING s; - s.hash = hash; - sorted_array<STRING>::range r = ::find_binary(strings.all(), s); + CString String; + String.m_Hash = Hash; + sorted_array<CString>::range r = ::find_binary(m_Strings.all(), String); if(r.empty()) return 0; - return r.front().replacement; + return r.front().m_Replacement; } -LOCALIZATIONDATABASE localization; +CLocalizationDatabase g_Localization; diff --git a/src/game/localization.h b/src/game/localization.h new file mode 100644 index 00000000..2e96ef04 --- /dev/null +++ b/src/game/localization.h @@ -0,0 +1,57 @@ +#ifndef GAME_LOCALIZATION_H +#define GAME_LOCALIZATION_H +#include <base/tl/string.h> +#include <base/tl/sorted_array.h> + +class CLocalizationDatabase +{ + class CString + { + public: + unsigned m_Hash; + + // TODO: do this as an const char * and put everything on a incremental heap + string m_Replacement; + + bool operator <(const CString &Other) const { return m_Hash < Other.m_Hash; } + bool operator <=(const CString &Other) const { return m_Hash <= Other.m_Hash; } + bool operator ==(const CString &Other) const { return m_Hash == Other.m_Hash; } + }; + + sorted_array<CString> m_Strings; + int m_CurrentVersion; + +public: + CLocalizationDatabase(); + + bool Load(const char *pFilename); + + int Version() { return m_CurrentVersion; } + + void AddString(const char *pOrgStr, const char *pNewStr); + const char *FindString(unsigned Hash); +}; + +extern CLocalizationDatabase g_Localization; + +class CLocConstString +{ + const char *m_pDefaultStr; + const char *m_pCurrentStr; + unsigned m_Hash; + int m_Version; +public: + CLocConstString(const char *pStr); + void Reload(); + + inline operator const char *() + { + if(m_Version != g_Localization.Version()) + Reload(); + return m_pCurrentStr; + } +}; + + +extern const char *Localize(const char *pStr); +#endif diff --git a/src/game/localization.hpp b/src/game/localization.hpp deleted file mode 100644 index 3f79d687..00000000 --- a/src/game/localization.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#include <base/tl/string.hpp> -#include <base/tl/sorted_array.hpp> - -class LOCALIZATIONDATABASE -{ - class STRING - { - public: - unsigned hash; - - // TODO: do this as an const char * and put everything on a incremental heap - string replacement; - - bool operator <(const STRING &other) const { return hash < other.hash; } - bool operator <=(const STRING &other) const { return hash <= other.hash; } - bool operator ==(const STRING &other) const { return hash == other.hash; } - }; - - sorted_array<STRING> strings; - int current_version; - -public: - LOCALIZATIONDATABASE(); - - bool load(const char *filename); - - int version() { return current_version; } - - void add_string(const char *org_str, const char *new_str); - const char *find_string(unsigned hash); -}; - -extern LOCALIZATIONDATABASE localization; - -class LOC_CONSTSTRING -{ - const char *default_str; - const char *current_str; - unsigned hash; - int version; -public: - LOC_CONSTSTRING(const char *str); - void reload(); - - inline operator const char *() - { - if(version != localization.version()) - reload(); - return current_str; - } -}; - - -extern const char *localize(const char *str); diff --git a/src/game/mapitems.h b/src/game/mapitems.h new file mode 100644 index 00000000..efbd96f2 --- /dev/null +++ b/src/game/mapitems.h @@ -0,0 +1,179 @@ +#ifndef GAME_MAPITEMS_H +#define GAME_MAPITEMS_H + +// layer types +enum +{ + LAYERTYPE_INVALID=0, + LAYERTYPE_GAME, // not used + LAYERTYPE_TILES, + LAYERTYPE_QUADS, + + MAPITEMTYPE_VERSION=0, + MAPITEMTYPE_INFO, + MAPITEMTYPE_IMAGE, + MAPITEMTYPE_ENVELOPE, + MAPITEMTYPE_GROUP, + MAPITEMTYPE_LAYER, + MAPITEMTYPE_ENVPOINTS, + + + CURVETYPE_STEP=0, + CURVETYPE_LINEAR, + CURVETYPE_SLOW, + CURVETYPE_FAST, + CURVETYPE_SMOOTH, + NUM_CURVETYPES, + + // game layer tiles + ENTITY_NULL=0, + ENTITY_SPAWN, + ENTITY_SPAWN_RED, + ENTITY_SPAWN_BLUE, + ENTITY_FLAGSTAND_RED, + ENTITY_FLAGSTAND_BLUE, + ENTITY_ARMOR_1, + ENTITY_HEALTH_1, + ENTITY_WEAPON_SHOTGUN, + ENTITY_WEAPON_GRENADE, + ENTITY_POWERUP_NINJA, + ENTITY_WEAPON_RIFLE, + NUM_ENTITIES, + + TILE_AIR=0, + TILE_SOLID, + TILE_DEATH, + TILE_NOHOOK, + + TILEFLAG_VFLIP=1, + TILEFLAG_HFLIP=2, + TILEFLAG_OPAQUE=4, + + LAYERFLAG_DETAIL=1, + + ENTITY_OFFSET=255-16*4, +}; + +struct CPoint +{ + int x, y; // 22.10 fixed point +}; + +struct CColor +{ + int r, g, b, a; +}; + +struct CQuad +{ + CPoint m_aPoints[5]; + CColor m_aColors[4]; + CPoint m_aTexcoords[4]; + + int m_PosEnv; + int m_PosEnvOffset; + + int m_ColorEnv; + int m_ColorEnvOffset; +}; + +struct CTile +{ + unsigned char m_Index; + unsigned char m_Flags; + unsigned char m_Skip; + unsigned char m_Reserved; +}; + +struct CMapItemImage +{ + int m_Version; + int m_Width; + int m_Height; + int m_External; + int m_ImageName; + int m_ImageData; +} ; + +struct CMapItemGroup_v1 +{ + int m_Version; + int m_OffsetX; + int m_OffsetY; + int m_ParallaxX; + int m_ParallaxY; + + int m_StartLayer; + int m_NumLayers; +} ; + + +struct CMapItemGroup : public CMapItemGroup_v1 +{ + enum { CURRENT_VERSION=2 }; + + int m_UseClipping; + int m_ClipX; + int m_ClipY; + int m_ClipW; + int m_ClipH; +} ; + +struct CMapItemLayer +{ + int m_Version; + int m_Type; + int m_Flags; +} ; + +struct CMapItemLayerTilemap +{ + CMapItemLayer m_Layer; + int m_Version; + + int m_Width; + int m_Height; + int m_Flags; + + CColor m_Color; + int m_ColorEnv; + int m_ColorEnvOffset; + + int m_Image; + int m_Data; +} ; + +struct CMapItemLayerQuads +{ + CMapItemLayer m_Layer; + int m_Version; + + int m_NumQuads; + int m_Data; + int m_Image; +} ; + +struct CMapItemVersion +{ + int m_Version; +} ; + +struct CEnvPoint +{ + int m_Time; // in ms + int m_Curvetype; + int m_aValues[4]; // 1-4 depending on envelope (22.10 fixed point) + + bool operator<(const CEnvPoint &Other) { return m_Time < Other.m_Time; } +} ; + +struct CMapItemEnvelope +{ + int m_Version; + int m_Channels; + int m_StartPoint; + int m_NumPoints; + int m_Name; +} ; + +#endif diff --git a/src/game/mapitems.hpp b/src/game/mapitems.hpp deleted file mode 100644 index 9c9936d2..00000000 --- a/src/game/mapitems.hpp +++ /dev/null @@ -1,178 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#ifndef GAME_MAPITEMS_H -#define GAME_MAPITEMS_H - -// layer types -enum -{ - LAYERTYPE_INVALID=0, - LAYERTYPE_GAME, // not used - LAYERTYPE_TILES, - LAYERTYPE_QUADS, - - MAPITEMTYPE_VERSION=0, - MAPITEMTYPE_INFO, - MAPITEMTYPE_IMAGE, - MAPITEMTYPE_ENVELOPE, - MAPITEMTYPE_GROUP, - MAPITEMTYPE_LAYER, - MAPITEMTYPE_ENVPOINTS, - - - CURVETYPE_STEP=0, - CURVETYPE_LINEAR, - CURVETYPE_SLOW, - CURVETYPE_FAST, - CURVETYPE_SMOOTH, - NUM_CURVETYPES, - - // game layer tiles - ENTITY_NULL=0, - ENTITY_SPAWN, - ENTITY_SPAWN_RED, - ENTITY_SPAWN_BLUE, - ENTITY_FLAGSTAND_RED, - ENTITY_FLAGSTAND_BLUE, - ENTITY_ARMOR_1, - ENTITY_HEALTH_1, - ENTITY_WEAPON_SHOTGUN, - ENTITY_WEAPON_GRENADE, - ENTITY_POWERUP_NINJA, - ENTITY_WEAPON_RIFLE, - NUM_ENTITIES, - - TILE_AIR=0, - TILE_SOLID, - TILE_DEATH, - TILE_NOHOOK, - - TILEFLAG_VFLIP=1, - TILEFLAG_HFLIP=2, - TILEFLAG_OPAQUE=4, - - LAYERFLAG_DETAIL=1, - - ENTITY_OFFSET=255-16*4, -}; - -typedef struct -{ - int x, y; // 22.10 fixed point -} POINT; - -typedef struct -{ - int r, g, b, a; -} COLOR; - -typedef struct -{ - POINT points[5]; - COLOR colors[4]; - POINT texcoords[4]; - - int pos_env; - int pos_env_offset; - - int color_env; - int color_env_offset; -} QUAD; - -typedef struct -{ - unsigned char index; - unsigned char flags; - unsigned char skip; - unsigned char reserved; -} TILE; - -typedef struct -{ - int version; - int width; - int height; - int external; - int image_name; - int image_data; -} MAPITEM_IMAGE; - -struct MAPITEM_GROUP_v1 -{ - int version; - int offset_x; - int offset_y; - int parallax_x; - int parallax_y; - - int start_layer; - int num_layers; -} ; - - -struct MAPITEM_GROUP : public MAPITEM_GROUP_v1 -{ - enum { CURRENT_VERSION=2 }; - - int use_clipping; - int clip_x; - int clip_y; - int clip_w; - int clip_h; -} ; - -typedef struct -{ - int version; - int type; - int flags; -} MAPITEM_LAYER; - -typedef struct -{ - MAPITEM_LAYER layer; - int version; - - int width; - int height; - int flags; - - COLOR color; - int color_env; - int color_env_offset; - - int image; - int data; -} MAPITEM_LAYER_TILEMAP; - -typedef struct -{ - MAPITEM_LAYER layer; - int version; - - int num_quads; - int data; - int image; -} MAPITEM_LAYER_QUADS; - -typedef struct -{ - int version; -} MAPITEM_VERSION; - -typedef struct -{ - int time; // in ms - int curvetype; - int values[4]; // 1-4 depending on envelope (22.10 fixed point) -} ENVPOINT; - -typedef struct -{ - int version; - int channels; - int start_point; - int num_points; - int name; -} MAPITEM_ENVELOPE; - -#endif diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 8ba91a80..839088dd 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -1,838 +1,820 @@ #include <new> -#include <engine/e_server_interface.h> -#include <engine/e_config.h> -#include <game/server/gamecontext.hpp> -#include <game/mapitems.hpp> +#include <engine/shared/config.h> +#include <game/server/gamecontext.h> +#include <game/mapitems.h> -#include "character.hpp" -#include "laser.hpp" -#include "projectile.hpp" +#include "character.h" +#include "laser.h" +#include "projectile.h" -struct INPUT_COUNT +//input count +struct CInputCount { - int presses; - int releases; + int m_Presses; + int m_Releases; }; -static INPUT_COUNT count_input(int prev, int cur) +CInputCount CountInput(int Prev, int Cur) { - INPUT_COUNT c = {0,0}; - prev &= INPUT_STATE_MASK; - cur &= INPUT_STATE_MASK; - int i = prev; - while(i != cur) + CInputCount c = {0, 0}; + Prev &= INPUT_STATE_MASK; + Cur &= INPUT_STATE_MASK; + int i = Prev; + + while(i != Cur) { i = (i+1)&INPUT_STATE_MASK; if(i&1) - c.presses++; + c.m_Presses++; else - c.releases++; + c.m_Releases++; } return c; } -MACRO_ALLOC_POOL_ID_IMPL(CHARACTER, MAX_CLIENTS) +MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS) -// player -CHARACTER::CHARACTER() -: ENTITY(NETOBJTYPE_CHARACTER) +// Character, "physical" player's part +CCharacter::CCharacter(CGameWorld *pWorld) +: CEntity(pWorld, NETOBJTYPE_CHARACTER) { - proximity_radius = phys_size; + m_ProximityRadius = g_CharPhysSize; + m_Health = 0; + m_Armor = 0; } -void CHARACTER::reset() +void CCharacter::Reset() { - destroy(); + Destroy(); } -bool CHARACTER::spawn(PLAYER *player, vec2 pos, int team) +bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos) { - player_state = PLAYERSTATE_UNKNOWN; - emote_stop = -1; - last_action = -1; - active_weapon = WEAPON_GUN; - last_weapon = WEAPON_HAMMER; - queued_weapon = -1; + m_PlayerState = PLAYERSTATE_UNKNOWN; + m_EmoteStop = -1; + m_LastAction = -1; + m_ActiveWeapon = WEAPON_GUN; + m_LastWeapon = WEAPON_HAMMER; + m_QueuedWeapon = -1; - //clear(); - this->player = player; - this->pos = pos; - this->team = team; + m_pPlayer = pPlayer; + m_Pos = Pos; - core.reset(); - core.world = &game.world.core; - core.pos = pos; - game.world.core.characters[player->client_id] = &core; - - reckoning_tick = 0; - mem_zero(&sendcore, sizeof(sendcore)); - mem_zero(&reckoningcore, sizeof(reckoningcore)); + m_Core.Reset(); + m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision()); + m_Core.m_Pos = m_Pos; + GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core; + + m_ReckoningTick = 0; + mem_zero(&m_SendCore, sizeof(m_SendCore)); + mem_zero(&m_ReckoningCore, sizeof(m_ReckoningCore)); - game.world.insert_entity(this); - alive = true; - player->force_balanced = false; + GameServer()->m_World.InsertEntity(this); + m_Alive = true; - game.controller->on_character_spawn(this); + GameServer()->m_pController->OnCharacterSpawn(this); return true; } -void CHARACTER::destroy() +void CCharacter::Destroy() { - game.world.core.characters[player->client_id] = 0; - alive = false; + GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0; + m_Alive = false; } -void CHARACTER::set_weapon(int w) +void CCharacter::SetWeapon(int W) { - if(w == active_weapon) + if(W == m_ActiveWeapon) return; - last_weapon = active_weapon; - queued_weapon = -1; - active_weapon = w; - if(active_weapon < 0 || active_weapon >= NUM_WEAPONS) - active_weapon = 0; + m_LastWeapon = m_ActiveWeapon; + m_QueuedWeapon = -1; + m_ActiveWeapon = W; + GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH); - game.create_sound(pos, SOUND_WEAPON_SWITCH); + if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS) + m_ActiveWeapon = 0; } -bool CHARACTER::is_grounded() +bool CCharacter::IsGrounded() { - if(col_check_point((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5))) + if(GameServer()->Collision()->CheckPoint(m_Pos.x+g_CharPhysSize/2, m_Pos.y+g_CharPhysSize/2+5)) return true; - if(col_check_point((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5))) + if(GameServer()->Collision()->CheckPoint(m_Pos.x-g_CharPhysSize/2, m_Pos.y+g_CharPhysSize/2+5)) return true; return false; } -int CHARACTER::handle_ninja() +void CCharacter::HandleNinja() { - if(active_weapon != WEAPON_NINJA) - return 0; + if(m_ActiveWeapon != WEAPON_NINJA) + return; - vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); + vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); - if ((server_tick() - ninja.activationtick) > (data->weapons.ninja.duration * server_tickspeed() / 1000)) + if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000)) { // time's up, return - weapons[WEAPON_NINJA].got = false; - active_weapon = last_weapon; - if(active_weapon == WEAPON_NINJA) - active_weapon = WEAPON_GUN; - set_weapon(active_weapon); - return 0; + m_aWeapons[WEAPON_NINJA].m_Got = false; + m_ActiveWeapon = m_LastWeapon; + if(m_ActiveWeapon == WEAPON_NINJA) + m_ActiveWeapon = WEAPON_GUN; + + SetWeapon(m_ActiveWeapon); + return; } - // force ninja weapon - set_weapon(WEAPON_NINJA); + // force ninja Weapon + SetWeapon(WEAPON_NINJA); - ninja.currentmovetime--; + m_Ninja.m_CurrentMoveTime--; - if (ninja.currentmovetime == 0) + if (m_Ninja.m_CurrentMoveTime == 0) { - // reset player velocity - core.vel *= 0.2f; - //return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON; + // reset velocity + m_Core.m_Vel *= 0.2f; } - if (ninja.currentmovetime > 0) + if (m_Ninja.m_CurrentMoveTime > 0) { - // Set player velocity - core.vel = ninja.activationdir * data->weapons.ninja.velocity; - vec2 oldpos = pos; - move_box(&core.pos, &core.vel, vec2(phys_size, phys_size), 0.0f); + // Set velocity + m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity; + vec2 OldPos = m_Pos; + GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(g_CharPhysSize, g_CharPhysSize), 0.f); + // reset velocity so the client doesn't predict stuff - core.vel = vec2(0.0f,0.0f); - if ((ninja.currentmovetime % 2) == 0) - { - //create_smoke(pos); - } + m_Core.m_Vel = vec2(0.f, 0.f); - // check if we hit anything along the way + // check if we Hit anything along the way { - CHARACTER *ents[64]; - vec2 dir = pos - oldpos; - float radius = phys_size * 2.0f; //length(dir * 0.5f); - vec2 center = oldpos + dir * 0.5f; - int num = game.world.find_entities(center, radius, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER); + CCharacter *aEnts[64]; + vec2 Dir = m_Pos - OldPos; + float Radius = g_CharPhysSize * 2.0f; + vec2 Center = OldPos + Dir * 0.5f; + int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, 64, NETOBJTYPE_CHARACTER); - for (int i = 0; i < num; i++) + for (int i = 0; i < Num; ++i) { - // Check if entity is a player - if (ents[i] == this) + if (aEnts[i] == this) continue; - // make sure we haven't hit this object before - bool balreadyhit = false; - for (int j = 0; j < numobjectshit; j++) + + // make sure we haven't Hit this object before + bool bAlreadyHit = false; + for (int j = 0; j < m_NumObjectsHit; j++) { - if (hitobjects[j] == ents[i]) - balreadyhit = true; + if (m_apHitObjects[j] == aEnts[i]) + bAlreadyHit = true; } - if (balreadyhit) + if (bAlreadyHit) continue; // check so we are sufficiently close - if (distance(ents[i]->pos, pos) > (phys_size * 2.0f)) + if (distance(aEnts[i]->m_Pos, m_Pos) > (g_CharPhysSize * 2.0f)) continue; - // hit a player, give him damage and stuffs... - game.create_sound(ents[i]->pos, SOUND_NINJA_HIT); + // Hit a player, give him damage and stuffs... + GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); // set his velocity to fast upward (for now) - if(numobjectshit < 10) - hitobjects[numobjectshit++] = ents[i]; + if(m_NumObjectsHit < 10) + m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; - ents[i]->take_damage(vec2(0,10.0f), data->weapons.ninja.base->damage, player->client_id,WEAPON_NINJA); + aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); } } - return 0; + + return; } - return 0; + return; } -void CHARACTER::do_weaponswitch() +void CCharacter::DoWeaponSwitch() { - if(reload_timer != 0) // make sure we have reloaded - return; - - if(queued_weapon == -1) // check for a queued weapon + // make sure we can switch + if(m_ReloadTimer != 0 || m_QueuedWeapon == -1 || m_aWeapons[WEAPON_NINJA].m_Got) return; - if(weapons[WEAPON_NINJA].got) // if we have ninja, no weapon selection is possible - return; - - // switch weapon - set_weapon(queued_weapon); + // switch Weapon + SetWeapon(m_QueuedWeapon); } -void CHARACTER::handle_weaponswitch() +void CCharacter::HandleWeaponSwitch() { - int wanted_weapon = active_weapon; - if(queued_weapon != -1) - wanted_weapon = queued_weapon; + int WantedWeapon = m_ActiveWeapon; + if(m_QueuedWeapon != -1) + WantedWeapon = m_QueuedWeapon; - // select weapon - int next = count_input(latest_previnput.next_weapon, latest_input.next_weapon).presses; - int prev = count_input(latest_previnput.prev_weapon, latest_input.prev_weapon).presses; + // select Weapon + int Next = CountInput(m_LatestPrevInput.m_NextWeapon, m_LatestInput.m_NextWeapon).m_Presses; + int Prev = CountInput(m_LatestPrevInput.m_PrevWeapon, m_LatestInput.m_PrevWeapon).m_Presses; - if(next < 128) // make sure we only try sane stuff + if(Next < 128) // make sure we only try sane stuff { - while(next) // next weapon selection + while(Next) // Next Weapon selection { - wanted_weapon = (wanted_weapon+1)%NUM_WEAPONS; - if(weapons[wanted_weapon].got) - next--; + WantedWeapon = (WantedWeapon+1)%NUM_WEAPONS; + if(m_aWeapons[WantedWeapon].m_Got) + Next--; } } - if(prev < 128) // make sure we only try sane stuff + if(Prev < 128) // make sure we only try sane stuff { - while(prev) // prev weapon selection + while(Prev) // Prev Weapon selection { - wanted_weapon = (wanted_weapon-1)<0?NUM_WEAPONS-1:wanted_weapon-1; - if(weapons[wanted_weapon].got) - prev--; + WantedWeapon = (WantedWeapon-1)<0?NUM_WEAPONS-1:WantedWeapon-1; + if(m_aWeapons[WantedWeapon].m_Got) + Prev--; } } - // direct weapon selection - if(latest_input.wanted_weapon) - wanted_weapon = input.wanted_weapon-1; + // Direct Weapon selection + if(m_LatestInput.m_WantedWeapon) + WantedWeapon = m_Input.m_WantedWeapon-1; // check for insane values - if(wanted_weapon >= 0 && wanted_weapon < NUM_WEAPONS && wanted_weapon != active_weapon && weapons[wanted_weapon].got) - queued_weapon = wanted_weapon; + if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got) + m_QueuedWeapon = WantedWeapon; - do_weaponswitch(); + DoWeaponSwitch(); } -void CHARACTER::fire_weapon() +void CCharacter::FireWeapon() { - if(reload_timer != 0) + if(m_ReloadTimer != 0) return; - do_weaponswitch(); + DoWeaponSwitch(); + vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); - vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); - - bool fullauto = false; - if(active_weapon == WEAPON_GRENADE || active_weapon == WEAPON_SHOTGUN || active_weapon == WEAPON_RIFLE) - fullauto = true; + bool FullAuto = false; + if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE) + FullAuto = true; // check if we gonna fire - bool will_fire = false; - if(count_input(latest_previnput.fire, latest_input.fire).presses) will_fire = true; - if(fullauto && (latest_input.fire&1) && weapons[active_weapon].ammo) will_fire = true; - if(!will_fire) + bool WillFire = false; + if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses) + WillFire = true; + + if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo) + WillFire = true; + + if(!WillFire) return; // check for ammo - if(!weapons[active_weapon].ammo) + if(!m_aWeapons[m_ActiveWeapon].m_Ammo) { // 125ms is a magical limit of how fast a human can click - reload_timer = 125 * server_tickspeed() / 1000;; - game.create_sound(pos, SOUND_WEAPON_NOAMMO); + m_ReloadTimer = 125 * Server()->TickSpeed() / 1000; + GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO); return; } - vec2 projectile_startpos = pos+direction*phys_size*0.75f; + vec2 ProjStartPos = m_Pos+Direction*g_CharPhysSize*0.75f; - switch(active_weapon) + switch(m_ActiveWeapon) { case WEAPON_HAMMER: { - // reset objects hit - numobjectshit = 0; - game.create_sound(pos, SOUND_HAMMER_FIRE); + // reset objects Hit + m_NumObjectsHit = 0; + GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE); - CHARACTER *ents[64]; - int hits = 0; - int num = game.world.find_entities(pos+direction*phys_size*0.75f, phys_size*0.5f, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER); + CCharacter *aEnts[64]; + int Hits = 0; + int Num = GameServer()->m_World.FindEntities(ProjStartPos, g_CharPhysSize*0.5f, (CEntity**)aEnts, + 64, NETOBJTYPE_CHARACTER); - for (int i = 0; i < num; i++) + for (int i = 0; i < Num; ++i) { - CHARACTER *target = ents[i]; - if (target == this) + CCharacter *Target = aEnts[i]; + + //for race mod or any other mod, which needs hammer hits through the wall remove second condition + if ((Target == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, Target->m_Pos, NULL, NULL)) continue; - - // hit a player, give him damage and stuffs... - vec2 fdir = normalize(ents[i]->pos - pos); // set his velocity to fast upward (for now) - game.create_hammerhit(pos); - ents[i]->take_damage(vec2(0,-1.0f), data->weapons.hammer.base->damage, player->client_id, active_weapon); - vec2 dir; - if (length(target->pos - pos) > 0.0f) - dir = normalize(target->pos - pos); + GameServer()->CreateHammerHit(m_Pos); + aEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); + + vec2 Dir; + if (length(Target->m_Pos - m_Pos) > 0.0f) + Dir = normalize(Target->m_Pos - m_Pos); else - dir = vec2(0,-1); + Dir = vec2(0.f, -1.f); - target->core.vel += normalize(dir + vec2(0,-1.1f)) * 10.0f; - hits++; + Target->m_Core.m_Vel += normalize(Dir + vec2(0.f, -1.1f)) * 10.0f; + Hits++; } - // if we hit anything, we have to wait for the reload - if(hits) - reload_timer = server_tickspeed()/3; + // if we Hit anything, we have to wait for the reload + if(Hits) + m_ReloadTimer = Server()->TickSpeed()/3; } break; case WEAPON_GUN: { - PROJECTILE *proj = new PROJECTILE(WEAPON_GUN, - player->client_id, - projectile_startpos, - direction, - (int)(server_tickspeed()*tuning.gun_lifetime), + CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_GUN, + m_pPlayer->GetCID(), + ProjStartPos, + Direction, + (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime), 1, 0, 0, -1, WEAPON_GUN); - // pack the projectile and send it to the client directly - NETOBJ_PROJECTILE p; - proj->fill_info(&p); + // pack the Projectile and send it to the client Directly + CNetObj_Projectile p; + Proj->FillInfo(&p); - msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); - msg_pack_int(1); - for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) - msg_pack_int(((int *)&p)[i]); - msg_pack_end(); - server_send_msg(player->client_id); - - game.create_sound(pos, SOUND_GUN_FIRE); + CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); + Msg.AddInt(1); + for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) + Msg.AddInt(((int *)&p)[i]); + + Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); + + GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE); } break; case WEAPON_SHOTGUN: { - int shotspread = 2; + int ShotSpread = 2; - msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); - msg_pack_int(shotspread*2+1); + CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); + Msg.AddInt(ShotSpread*2+1); - for(int i = -shotspread; i <= shotspread; i++) + for(int i = -ShotSpread; i <= ShotSpread; ++i) { - float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; - float a = get_angle(direction); - a += spreading[i+2]; - float v = 1-(abs(i)/(float)shotspread); - float speed = mix((float)tuning.shotgun_speeddiff, 1.0f, v); - PROJECTILE *proj = new PROJECTILE(WEAPON_SHOTGUN, - player->client_id, - projectile_startpos, - vec2(cosf(a), sinf(a))*speed, - (int)(server_tickspeed()*tuning.shotgun_lifetime), + float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; + float a = GetAngle(Direction); + a += Spreading[i+2]; + float v = 1-(absolute(i)/(float)ShotSpread); + float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v); + CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, + m_pPlayer->GetCID(), + ProjStartPos, + vec2(cosf(a), sinf(a))*Speed, + (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime), 1, 0, 0, -1, WEAPON_SHOTGUN); - // pack the projectile and send it to the client directly - NETOBJ_PROJECTILE p; - proj->fill_info(&p); + // pack the Projectile and send it to the client Directly + CNetObj_Projectile p; + Proj->FillInfo(&p); - for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) - msg_pack_int(((int *)&p)[i]); + for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) + Msg.AddInt(((int *)&p)[i]); } - msg_pack_end(); - server_send_msg(player->client_id); + Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID()); - game.create_sound(pos, SOUND_SHOTGUN_FIRE); + GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE); } break; case WEAPON_GRENADE: { - PROJECTILE *proj = new PROJECTILE(WEAPON_GRENADE, - player->client_id, - projectile_startpos, - direction, - (int)(server_tickspeed()*tuning.grenade_lifetime), - 1, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); - - // pack the projectile and send it to the client directly - NETOBJ_PROJECTILE p; - proj->fill_info(&p); + CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_GRENADE, + m_pPlayer->GetCID(), + ProjStartPos, + Direction, + (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime), + 1, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); + + // pack the Projectile and send it to the client Directly + CNetObj_Projectile p; + Proj->FillInfo(&p); + + CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); + Msg.AddInt(1); + for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) + Msg.AddInt(((int *)&p)[i]); + Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); - msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); - msg_pack_int(1); - for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) - msg_pack_int(((int *)&p)[i]); - msg_pack_end(); - server_send_msg(player->client_id); - - game.create_sound(pos, SOUND_GRENADE_FIRE); + GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE); } break; case WEAPON_RIFLE: { - new LASER(pos, direction, tuning.laser_reach, player->client_id); - game.create_sound(pos, SOUND_RIFLE_FIRE); + new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID()); + GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE); } break; case WEAPON_NINJA: { - attack_tick = server_tick(); - ninja.activationdir = direction; - ninja.currentmovetime = data->weapons.ninja.movetime * server_tickspeed() / 1000; - - //reload_timer = data->weapons.ninja.base->firedelay * server_tickspeed() / 1000 + server_tick(); + // reset Hit objects + m_NumObjectsHit = 0; - // reset hit objects - numobjectshit = 0; + m_AttackTick = Server()->Tick(); + m_Ninja.m_ActivationDir = Direction; + m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000; - game.create_sound(pos, SOUND_NINJA_FIRE); - + GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE); } break; } - - if(weapons[active_weapon].ammo > 0) // -1 == unlimited - weapons[active_weapon].ammo--; - attack_tick = server_tick(); - if(!reload_timer) - reload_timer = data->weapons.id[active_weapon].firedelay * server_tickspeed() / 1000; + + m_AttackTick = Server()->Tick(); + + if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited + m_aWeapons[m_ActiveWeapon].m_Ammo--; + + if(!m_ReloadTimer) + m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000; } -int CHARACTER::handle_weapons() +void CCharacter::HandleWeapons() { - vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); - - /* - if(config.dbg_stress) - { - for(int i = 0; i < NUM_WEAPONS; i++) - { - weapons[i].got = true; - weapons[i].ammo = 10; - } - - if(reload_timer) // twice as fast reload - reload_timer--; - } */ - - //if(active_weapon == WEAPON_NINJA) - handle_ninja(); - + //ninja + HandleNinja(); + + vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); // check reload timer - if(reload_timer) + if(m_ReloadTimer) { - reload_timer--; - return 0; + m_ReloadTimer--; + return; } - - /* - if (active_weapon == WEAPON_NINJA) - { - // don't update other weapons while ninja is active - return handle_ninja(); - }*/ - // fire weapon, if wanted - fire_weapon(); + // fire Weapon, if wanted + FireWeapon(); // ammo regen - int ammoregentime = data->weapons.id[active_weapon].ammoregentime; - if(ammoregentime) + int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; + if(AmmoRegenTime) { // If equipped and not active, regen ammo? - if (reload_timer <= 0) + if (m_ReloadTimer <= 0) { - if (weapons[active_weapon].ammoregenstart < 0) - weapons[active_weapon].ammoregenstart = server_tick(); + if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0) + m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick(); - if ((server_tick() - weapons[active_weapon].ammoregenstart) >= ammoregentime * server_tickspeed() / 1000) + if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000) { // Add some ammo - weapons[active_weapon].ammo = min(weapons[active_weapon].ammo + 1, 10); - weapons[active_weapon].ammoregenstart = -1; + m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10); + m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } else { - weapons[active_weapon].ammoregenstart = -1; + m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } - return 0; + return; +} + +bool CCharacter::GiveWeapon(int Weapon, int Ammo) +{ + if(m_aWeapons[Weapon].m_Ammo < g_pData->m_Weapons.m_aId[Weapon].m_Maxammo || !m_aWeapons[Weapon].m_Got) + { + m_aWeapons[Weapon].m_Got = true; + m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo); + return true; + } + return false; +} + +void CCharacter::GiveNinja() +{ + m_Ninja.m_ActivationTick = Server()->Tick(); + m_aWeapons[WEAPON_NINJA].m_Got = true; + m_aWeapons[WEAPON_NINJA].m_Ammo = -1; + m_LastWeapon = m_ActiveWeapon; + m_ActiveWeapon = WEAPON_NINJA; + + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA); } -void CHARACTER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input) +void CCharacter::SetEmote(int Emote, int Tick) +{ + m_EmoteType = Emote; + m_EmoteStop = Tick; +} + +void CCharacter::OnPredictedInput(CNetObj_PlayerInput *pNewInput) { // check for changes - if(mem_comp(&input, new_input, sizeof(NETOBJ_PLAYER_INPUT)) != 0) - last_action = server_tick(); + if(mem_comp(&m_Input, pNewInput, sizeof(CNetObj_PlayerInput)) != 0) + m_LastAction = Server()->Tick(); // copy new input - mem_copy(&input, new_input, sizeof(input)); - num_inputs++; + mem_copy(&m_Input, pNewInput, sizeof(m_Input)); + m_NumInputs++; // or are not allowed to aim in the center - if(input.target_x == 0 && input.target_y == 0) - input.target_y = -1; + if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0) + m_Input.m_TargetY = -1; } -void CHARACTER::on_direct_input(NETOBJ_PLAYER_INPUT *new_input) +void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput) { - mem_copy(&latest_previnput, &latest_input, sizeof(latest_input)); - mem_copy(&latest_input, new_input, sizeof(latest_input)); + mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); + mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput)); - if(num_inputs > 2 && team != -1) + if(m_NumInputs > 2 && m_pPlayer->GetTeam() != -1) { - handle_weaponswitch(); - fire_weapon(); + HandleWeaponSwitch(); + FireWeapon(); } - mem_copy(&latest_previnput, &latest_input, sizeof(latest_input)); + mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); } -void CHARACTER::tick() +void CCharacter::Tick() { - if(player->force_balanced) + if(m_pPlayer->m_ForceBalanced) { - char buf[128]; - str_format(buf, sizeof(buf), "You were moved to %s due to team balancing", game.controller->get_team_name(team)); - game.send_broadcast(buf, player->client_id); + char Buf[128]; + str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam())); + GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID()); - player->force_balanced = false; + m_pPlayer->m_ForceBalanced = false; } - //player_core core; - //core.pos = pos; - //core.jumped = jumped; - core.input = input; - core.tick(true); + m_Core.m_Input = m_Input; + m_Core.Tick(true); - float phys_size = 28.0f; // handle death-tiles - if(col_get((int)(pos.x+phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH || - col_get((int)(pos.x+phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH || - col_get((int)(pos.x-phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH || - col_get((int)(pos.x-phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH) + if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+g_CharPhysSize/3.f, m_Pos.y-g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH || + GameServer()->Collision()->GetCollisionAt(m_Pos.x+g_CharPhysSize/3.f, m_Pos.y+g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH || + GameServer()->Collision()->GetCollisionAt(m_Pos.x-g_CharPhysSize/3.f, m_Pos.y-g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH || + GameServer()->Collision()->GetCollisionAt(m_Pos.x-g_CharPhysSize/3.f, m_Pos.y+g_CharPhysSize/3.f)&CCollision::COLFLAG_DEATH) { - die(player->client_id, WEAPON_WORLD); + Die(m_pPlayer->GetCID(), WEAPON_WORLD); } - // handle weapons - handle_weapons(); + // handle Weapons + HandleWeapons(); - player_state = input.player_state; + m_PlayerState = m_Input.m_PlayerState; // Previnput - previnput = input; + m_PrevInput = m_Input; return; } -void CHARACTER::tick_defered() +void CCharacter::TickDefered() { // advance the dummy { - WORLD_CORE tempworld; - reckoningcore.world = &tempworld; - reckoningcore.tick(false); - reckoningcore.move(); - reckoningcore.quantize(); + CWorldCore TempWorld; + m_ReckoningCore.Init(&TempWorld, GameServer()->Collision()); + m_ReckoningCore.Tick(false); + m_ReckoningCore.Move(); + m_ReckoningCore.Quantize(); } - //lastsentcore; - /*if(!dead) - {*/ - vec2 start_pos = core.pos; - vec2 start_vel = core.vel; - bool stuck_before = test_box(core.pos, vec2(28.0f, 28.0f)); - - core.move(); - bool stuck_after_move = test_box(core.pos, vec2(28.0f, 28.0f)); - core.quantize(); - bool stuck_after_quant = test_box(core.pos, vec2(28.0f, 28.0f)); - pos = core.pos; - - if(!stuck_before && (stuck_after_move || stuck_after_quant)) - { - dbg_msg("player", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", - stuck_before, - stuck_after_move, - stuck_after_quant, - start_pos.x, start_pos.y, - start_vel.x, start_vel.y, - *((unsigned *)&start_pos.x), *((unsigned *)&start_pos.y), - *((unsigned *)&start_vel.x), *((unsigned *)&start_vel.y)); - } + //lastsentcore + vec2 StartPos = m_Core.m_Pos; + vec2 StartVel = m_Core.m_Vel; + bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + + m_Core.Move(); + bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + m_Core.Quantize(); + bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); + m_Pos = m_Core.m_Pos; + + if(!StuckBefore && (StuckAfterMove || StuckAfterQuant)) + { + dbg_msg("char_core", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", + StuckBefore, + StuckAfterMove, + StuckAfterQuant, + StartPos.x, StartPos.y, + StartVel.x, StartVel.y, + *((unsigned *)&StartPos.x), *((unsigned *)&StartPos.y), + *((unsigned *)&StartVel.x), *((unsigned *)&StartVel.y)); + } - int events = core.triggered_events; - int mask = cmask_all_except_one(player->client_id); - - if(events&COREEVENT_GROUND_JUMP) game.create_sound(pos, SOUND_PLAYER_JUMP, mask); - - //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); - if(events&COREEVENT_HOOK_ATTACH_PLAYER) game.create_sound(pos, SOUND_HOOK_ATTACH_PLAYER, cmask_all()); - if(events&COREEVENT_HOOK_ATTACH_GROUND) game.create_sound(pos, SOUND_HOOK_ATTACH_GROUND, mask); - if(events&COREEVENT_HOOK_HIT_NOHOOK) game.create_sound(pos, SOUND_HOOK_NOATTACH, mask); - //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); - //} - - if(team == -1) + int Events = m_Core.m_TriggeredEvents; + int Mask = CmaskAllExceptOne(m_pPlayer->GetCID()); + + if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask); + + if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll()); + if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask); + if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask); + + + if(m_pPlayer->GetTeam() == -1) { - pos.x = input.target_x; - pos.y = input.target_y; + m_Pos.x = m_Input.m_TargetX; + m_Pos.y = m_Input.m_TargetY; } - // update the sendcore if needed + // update the m_SendCore if needed { - NETOBJ_CHARACTER predicted; - NETOBJ_CHARACTER current; - mem_zero(&predicted, sizeof(predicted)); - mem_zero(¤t, sizeof(current)); - reckoningcore.write(&predicted); - core.write(¤t); + CNetObj_Character Predicted; + CNetObj_Character Current; + mem_zero(&Predicted, sizeof(Predicted)); + mem_zero(&Current, sizeof(Current)); + m_ReckoningCore.Write(&Predicted); + m_Core.Write(&Current); // only allow dead reackoning for a top of 3 seconds - if(reckoning_tick+server_tickspeed()*3 < server_tick() || mem_comp(&predicted, ¤t, sizeof(NETOBJ_CHARACTER)) != 0) + if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0) { - reckoning_tick = server_tick(); - sendcore = core; - reckoningcore = core; + m_ReckoningTick = Server()->Tick(); + m_SendCore = m_Core; + m_ReckoningCore = m_Core; } } } -bool CHARACTER::increase_health(int amount) +bool CCharacter::IncreaseHealth(int Amount) { - if(health >= 10) + if(m_Health >= 10) return false; - health = clamp(health+amount, 0, 10); + m_Health = clamp(m_Health+Amount, 0, 10); return true; } -bool CHARACTER::increase_armor(int amount) +bool CCharacter::IncreaseArmor(int Amount) { - if(armor >= 10) + if(m_Armor >= 10) return false; - armor = clamp(armor+amount, 0, 10); + m_Armor = clamp(m_Armor+Amount, 0, 10); return true; } -void CHARACTER::die(int killer, int weapon) +void CCharacter::Die(int Killer, int Weapon) { - /*if (dead || team == -1) - return;*/ - int mode_special = game.controller->on_character_death(this, game.players[killer], weapon); + int ModeSpecial = GameServer()->m_pController->OnCharacterDeath(this, GameServer()->m_apPlayers[Killer], Weapon); dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d", - killer, server_clientname(killer), - player->client_id, server_clientname(player->client_id), weapon, mode_special); + Killer, Server()->ClientName(Killer), + m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), Weapon, ModeSpecial); // send the kill message - NETMSG_SV_KILLMSG msg; - msg.killer = killer; - msg.victim = player->client_id; - msg.weapon = weapon; - msg.mode_special = mode_special; - msg.pack(MSGFLAG_VITAL); - server_send_msg(-1); + CNetMsg_Sv_KillMsg Msg; + Msg.m_Killer = Killer; + Msg.m_Victim = m_pPlayer->GetCID(); + Msg.m_Weapon = Weapon; + Msg.m_ModeSpecial = ModeSpecial; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1); // a nice sound - game.create_sound(pos, SOUND_PLAYER_DIE); - - // set dead state - // TODO: do stuff here - /* - die_pos = pos; - dead = true; - */ + GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE); // this is for auto respawn after 3 secs - player->die_tick = server_tick(); + m_pPlayer->m_DieTick = Server()->Tick(); - alive = false; - game.world.remove_entity(this); - game.world.core.characters[player->client_id] = 0; - game.create_death(pos, player->client_id); + m_Alive = false; + GameServer()->m_World.RemoveEntity(this); + GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0; + GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID()); // we got to wait 0.5 secs before respawning - player->respawn_tick = server_tick()+server_tickspeed()/2; + m_pPlayer->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2; } -bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon) +bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) { - core.vel += force; + m_Core.m_Vel += Force; - if(game.controller->is_friendly_fire(player->client_id, from) && !config.sv_teamdamage) + if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage) return false; - // player only inflicts half damage on self - if(from == player->client_id) - dmg = max(1, dmg/2); + // m_pPlayer only inflicts half damage on self + if(From == m_pPlayer->GetCID()) + Dmg = max(1, Dmg/2); - damage_taken++; + m_DamageTaken++; // create healthmod indicator - if(server_tick() < damage_taken_tick+25) + if(Server()->Tick() < m_DamageTakenTick+25) { // make sure that the damage indicators doesn't group together - game.create_damageind(pos, damage_taken*0.25f, dmg); + GameServer()->CreateDamageInd(m_Pos, m_DamageTaken*0.25f, Dmg); } else { - damage_taken = 0; - game.create_damageind(pos, 0, dmg); + m_DamageTaken = 0; + GameServer()->CreateDamageInd(m_Pos, 0, Dmg); } - if(dmg) + if(Dmg) { - if(armor) + if(m_Armor) { - if(dmg > 1) + if(Dmg > 1) { - health--; - dmg--; + m_Health--; + Dmg--; } - if(dmg > armor) + if(Dmg > m_Armor) { - dmg -= armor; - armor = 0; + Dmg -= m_Armor; + m_Armor = 0; } else { - armor -= dmg; - dmg = 0; + m_Armor -= Dmg; + Dmg = 0; } } - health -= dmg; + m_Health -= Dmg; } - damage_taken_tick = server_tick(); + m_DamageTakenTick = Server()->Tick(); - // do damage hit sound - if(from >= 0 && from != player->client_id && game.players[from]) - game.create_sound(game.players[from]->view_pos, SOUND_HIT, cmask_one(from)); + // do damage Hit sound + if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From]) + GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, CmaskOne(From)); // check for death - if(health <= 0) + if(m_Health <= 0) { - die(from, weapon); + Die(From, Weapon); // set attacker's face to happy (taunt!) - if (from >= 0 && from != player->client_id && game.players[from]) + if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From]) { - CHARACTER *chr = game.players[from]->get_character(); - if (chr) + CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter(); + if (pChr) { - chr->emote_type = EMOTE_HAPPY; - chr->emote_stop = server_tick() + server_tickspeed(); + pChr->m_EmoteType = EMOTE_HAPPY; + pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed(); } } return false; } - if (dmg > 2) - game.create_sound(pos, SOUND_PLAYER_PAIN_LONG); + if (Dmg > 2) + GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG); else - game.create_sound(pos, SOUND_PLAYER_PAIN_SHORT); + GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT); - emote_type = EMOTE_PAIN; - emote_stop = server_tick() + 500 * server_tickspeed() / 1000; + m_EmoteType = EMOTE_PAIN; + m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000; - // spawn blood? return true; } -void CHARACTER::snap(int snapping_client) +void CCharacter::Snap(int SnappingClient) { - if(networkclipped(snapping_client)) + if(NetworkClipped(SnappingClient)) return; - NETOBJ_CHARACTER *character = (NETOBJ_CHARACTER *)snap_new_item(NETOBJTYPE_CHARACTER, player->client_id, sizeof(NETOBJ_CHARACTER)); + CNetObj_Character *Character = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character))); - // write down the core - if(game.world.paused) + // write down the m_Core + if(GameServer()->m_World.m_Paused) { // no dead reckoning when paused because the client doesn't know // how far to perform the reckoning - character->tick = 0; - core.write(character); + Character->m_Tick = 0; + m_Core.Write(Character); } else { - character->tick = reckoning_tick; - sendcore.write(character); + Character->m_Tick = m_ReckoningTick; + m_SendCore.Write(Character); } // set emote - if (emote_stop < server_tick()) + if (m_EmoteStop < Server()->Tick()) { - emote_type = EMOTE_NORMAL; - emote_stop = -1; + m_EmoteType = EMOTE_NORMAL; + m_EmoteStop = -1; } - character->emote = emote_type; + Character->m_Emote = m_EmoteType; - character->ammocount = 0; - character->health = 0; - character->armor = 0; + Character->m_AmmoCount = 0; + Character->m_Health = 0; + Character->m_Armor = 0; - character->weapon = active_weapon; - character->attacktick = attack_tick; + Character->m_Weapon = m_ActiveWeapon; + Character->m_AttackTick = m_AttackTick; - character->direction = input.direction; + Character->m_Direction = m_Input.m_Direction; - if(player->client_id == snapping_client) + if(m_pPlayer->GetCID() == SnappingClient) { - character->health = health; - character->armor = armor; - if(weapons[active_weapon].ammo > 0) - character->ammocount = weapons[active_weapon].ammo; + Character->m_Health = m_Health; + Character->m_Armor = m_Armor; + if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) + Character->m_AmmoCount = m_aWeapons[m_ActiveWeapon].m_Ammo; } - if (character->emote == EMOTE_NORMAL) + if (Character->m_Emote == EMOTE_NORMAL) { - if(250 - ((server_tick() - last_action)%(250)) < 5) - character->emote = EMOTE_BLINK; + if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5) + Character->m_Emote = EMOTE_BLINK; } - character->player_state = player_state; + Character->m_PlayerState = m_PlayerState; } diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h new file mode 100644 index 00000000..30c6586f --- /dev/null +++ b/src/game/server/entities/character.h @@ -0,0 +1,133 @@ +#ifndef GAME_SERVER_ENTITIES_CHARACTER_H +#define GAME_SERVER_ENTITIES_CHARACTER_H + +#include <game/server/entity.h> +#include <game/generated/server_data.h> +#include <game/generated/protocol.h> + +#include <game/gamecore.h> + +//character's size +const int g_CharPhysSize = 28; + +enum +{ + WEAPON_GAME = -3, // team switching etc + WEAPON_SELF = -2, // console kill command + WEAPON_WORLD = -1, // death tiles etc +}; + +class CCharacter : public CEntity +{ + MACRO_ALLOC_POOL_ID() + +public: + CCharacter(CGameWorld *pWorld); + + virtual void Reset(); + virtual void Destroy(); + virtual void Tick(); + virtual void TickDefered(); + virtual void Snap(int SnappingClient); + + bool IsGrounded(); + + void SetWeapon(int W); + void HandleWeaponSwitch(); + void DoWeaponSwitch(); + + void HandleWeapons(); + void HandleNinja(); + + void OnPredictedInput(CNetObj_PlayerInput *pNewInput); + void OnDirectInput(CNetObj_PlayerInput *pNewInput); + void FireWeapon(); + + void Die(int Killer, int Weapon); + bool TakeDamage(vec2 Force, int Dmg, int From, int Weapon); + + bool Spawn(class CPlayer *pPlayer, vec2 Pos); + bool Remove(); + + bool IncreaseHealth(int Amount); + bool IncreaseArmor(int Amount); + + bool GiveWeapon(int Weapon, int Ammo); + void GiveNinja(); + + void SetEmote(int Emote, int Tick); + + const bool IsAlive() { return m_Alive; } + class CPlayer *GetPlayer() { return m_pPlayer; } + +private: + // player controlling this character + class CPlayer *m_pPlayer; + + bool m_Alive; + + // weapon info + CEntity *m_apHitObjects[10]; + int m_NumObjectsHit; + + struct WeaponStat + { + int m_AmmoRegenStart; + int m_Ammo; + int m_Ammocost; + bool m_Got; + + } m_aWeapons[NUM_WEAPONS]; + + int m_ActiveWeapon; + int m_LastWeapon; + int m_QueuedWeapon; + + int m_ReloadTimer; + int m_AttackTick; + + int m_DamageTaken; + + int m_EmoteType; + int m_EmoteStop; + + // last tick that the player took any action ie some input + int m_LastAction; + + // these are non-heldback inputs + CNetObj_PlayerInput m_LatestPrevInput; + CNetObj_PlayerInput m_LatestInput; + + // input + CNetObj_PlayerInput m_PrevInput; + CNetObj_PlayerInput m_Input; + int m_NumInputs; + int m_Jumped; + + int m_DamageTakenTick; + + int m_Health; + int m_Armor; + + // ninja + struct + { + vec2 m_ActivationDir; + int m_ActivationTick; + int m_CurrentMoveTime; + + } m_Ninja; + + int m_PlayerState;// if the client is chatting, accessing a menu or so + + // the player core for the physics + CCharacterCore m_Core; + + // info for dead reckoning + int m_ReckoningTick; // tick that we are performing dead reckoning From + CCharacterCore m_SendCore; // core that we should send + CCharacterCore m_ReckoningCore; // the dead reckoning core + +}; + +#endif diff --git a/src/game/server/entities/character.hpp b/src/game/server/entities/character.hpp deleted file mode 100644 index bd2f7afe..00000000 --- a/src/game/server/entities/character.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#ifndef GAME_SERVER_ENTITY_CHARACTER_H -#define GAME_SERVER_ENTITY_CHARACTER_H - -#include <game/server/entity.hpp> -#include <game/generated/gs_data.hpp> -#include <game/generated/g_protocol.hpp> - -#include <game/gamecore.hpp> - -enum -{ - WEAPON_GAME = -3, // team switching etc - WEAPON_SELF = -2, // console kill command - WEAPON_WORLD = -1, // death tiles etc -}; - -class CHARACTER : public ENTITY -{ - MACRO_ALLOC_POOL_ID() -public: - // player controlling this character - class PLAYER *player; - - bool alive; - - // weapon info - ENTITY *hitobjects[10]; - int numobjectshit; - struct WEAPONSTAT - { - int ammoregenstart; - int ammo; - int ammocost; - bool got; - } weapons[NUM_WEAPONS]; - - int active_weapon; - int last_weapon; - int queued_weapon; - - int reload_timer; - int attack_tick; - - int damage_taken; - - int emote_type; - int emote_stop; - - // TODO: clean this up - char skin_name[64]; - int use_custom_color; - int color_body; - int color_feet; - - int last_action; // last tick that the player took any action ie some input - - // these are non-heldback inputs - NETOBJ_PLAYER_INPUT latest_previnput; - NETOBJ_PLAYER_INPUT latest_input; - - // input - NETOBJ_PLAYER_INPUT previnput; - NETOBJ_PLAYER_INPUT input; - int num_inputs; - int jumped; - - int damage_taken_tick; - - int health; - int armor; - - // ninja - struct - { - vec2 activationdir; - int activationtick; - int currentmovetime; - } ninja; - - // - //int score; - int team; - int player_state; // if the client is chatting, accessing a menu or so - - // the player core for the physics - CHARACTER_CORE core; - - // info for dead reckoning - int reckoning_tick; // tick that we are performing dead reckoning from - CHARACTER_CORE sendcore; // core that we should send - CHARACTER_CORE reckoningcore; // the dead reckoning core - - // - CHARACTER(); - - virtual void reset(); - virtual void destroy(); - - bool is_grounded(); - - void set_weapon(int w); - - void handle_weaponswitch(); - void do_weaponswitch(); - - int handle_weapons(); - int handle_ninja(); - - void on_predicted_input(NETOBJ_PLAYER_INPUT *new_input); - void on_direct_input(NETOBJ_PLAYER_INPUT *new_input); - void fire_weapon(); - - void die(int killer, int weapon); - - bool take_damage(vec2 force, int dmg, int from, int weapon); - - - bool spawn(PLAYER *player, vec2 pos, int team); - //bool init_tryspawn(int team); - bool remove(); - - static const int phys_size = 28; - - virtual void tick(); - virtual void tick_defered(); - virtual void snap(int snapping_client); - - bool increase_health(int amount); - bool increase_armor(int amount); -}; - -#endif diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 2c6fa0ff..6bc26074 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -1,115 +1,105 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <engine/e_server_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/server/gamecontext.hpp> -#include "laser.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include <game/generated/protocol.h> +#include <game/server/gamecontext.h> +#include "laser.h" -////////////////////////////////////////////////// -// laser -////////////////////////////////////////////////// -LASER::LASER(vec2 pos, vec2 direction, float start_energy, int owner) -: ENTITY(NETOBJTYPE_LASER) +CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner) +: CEntity(pGameWorld, NETOBJTYPE_LASER) { - this->pos = pos; - this->owner = owner; - energy = start_energy; - dir = direction; - bounces = 0; - do_bounce(); - - game.world.insert_entity(this); + m_Pos = Pos; + m_Owner = Owner; + m_Energy = StartEnergy; + m_Dir = Direction; + m_Bounces = 0; + m_EvalTick = 0; + GameWorld()->InsertEntity(this); + DoBounce(); } -bool LASER::hit_character(vec2 from, vec2 to) +bool CLaser::HitCharacter(vec2 From, vec2 To) { - vec2 at; - CHARACTER *owner_char = game.get_player_char(owner); - CHARACTER *hit = game.world.intersect_character(pos, to, 0.0f, at, owner_char); - if(!hit) + vec2 At; + CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner); + CCharacter *Hit = GameServer()->m_World.IntersectCharacter(m_Pos, To, 0.f, At, OwnerChar); + if(!Hit) return false; - this->from = from; - pos = at; - energy = -1; - hit->take_damage(vec2(0,0), tuning.laser_damage, owner, WEAPON_RIFLE); + m_From = From; + m_Pos = At; + m_Energy = -1; + Hit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE); return true; } -void LASER::do_bounce() +void CLaser::DoBounce() { - eval_tick = server_tick(); + m_EvalTick = Server()->Tick(); - if(energy < 0) + if(m_Energy < 0) { - //dbg_msg("laser", "%d removed", server_tick()); - game.world.destroy_entity(this); + GameServer()->m_World.DestroyEntity(this); return; } - vec2 to = pos + dir*energy; - vec2 org_to = to; + vec2 To = m_Pos + m_Dir * m_Energy; + vec2 OrgTo = To; - if(col_intersect_line(pos, to, 0x0, &to)) + if(GameServer()->Collision()->IntersectLine(m_Pos, To, 0x0, &To)) { - if(!hit_character(pos, to)) + if(!HitCharacter(m_Pos, To)) { // intersected - from = pos; - pos = to; + m_From = m_Pos; + m_Pos = To; - vec2 temp_pos = pos; - vec2 temp_dir = dir*4.0f; + vec2 TempPos = m_Pos; + vec2 TempDir = m_Dir * 4.0f; - move_point(&temp_pos, &temp_dir, 1.0f, 0); - pos = temp_pos; - dir = normalize(temp_dir); + GameServer()->Collision()->MovePoint(&TempPos, &TempDir, 1.0f, 0); + m_Pos = TempPos; + m_Dir = normalize(TempDir); - energy -= distance(from, pos) + tuning.laser_bounce_cost; - bounces++; + m_Energy -= distance(m_From, m_Pos) + GameServer()->Tuning()->m_LaserBounceCost; + m_Bounces++; - if(bounces > tuning.laser_bounce_num) - energy = -1; + if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum) + m_Energy = -1; - game.create_sound(pos, SOUND_RIFLE_BOUNCE); + GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE); } } else { - if(!hit_character(pos, to)) + if(!HitCharacter(m_Pos, To)) { - from = pos; - pos = to; - energy = -1; + m_From = m_Pos; + m_Pos = To; + m_Energy = -1; } } - - //dbg_msg("laser", "%d done %f %f %f %f", server_tick(), from.x, from.y, pos.x, pos.y); } -void LASER::reset() +void CLaser::Reset() { - game.world.destroy_entity(this); + GameServer()->m_World.DestroyEntity(this); } -void LASER::tick() +void CLaser::Tick() { - if(server_tick() > eval_tick+(server_tickspeed()*tuning.laser_bounce_delay)/1000.0f) - { - do_bounce(); - } - + if(Server()->Tick() > m_EvalTick+(Server()->TickSpeed()*GameServer()->Tuning()->m_LaserBounceDelay)/1000.0f) + DoBounce(); } -void LASER::snap(int snapping_client) +void CLaser::Snap(int SnappingClient) { - if(networkclipped(snapping_client)) + if(NetworkClipped(SnappingClient)) return; - NETOBJ_LASER *obj = (NETOBJ_LASER *)snap_new_item(NETOBJTYPE_LASER, id, sizeof(NETOBJ_LASER)); - obj->x = (int)pos.x; - obj->y = (int)pos.y; - obj->from_x = (int)from.x; - obj->from_y = (int)from.y; - obj->start_tick = eval_tick; + CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, m_Id, sizeof(CNetObj_Laser))); + pObj->m_X = (int)m_Pos.x; + pObj->m_Y = (int)m_Pos.y; + pObj->m_FromX = (int)m_From.x; + pObj->m_FromY = (int)m_From.y; + pObj->m_StartTick = m_EvalTick; } diff --git a/src/game/server/entities/laser.h b/src/game/server/entities/laser.h new file mode 100644 index 00000000..040cfb4c --- /dev/null +++ b/src/game/server/entities/laser.h @@ -0,0 +1,28 @@ +#ifndef GAME_SERVER_ENTITIES_LASER_H +#define GAME_SERVER_ENTITIES_LASER_H + +#include <game/server/entity.h> + +class CLaser : public CEntity +{ +public: + CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner); + + virtual void Reset(); + virtual void Tick(); + virtual void Snap(int SnappingClient); + +protected: + bool HitCharacter(vec2 From, vec2 To); + void DoBounce(); + +private: + vec2 m_From; + vec2 m_Dir; + float m_Energy; + int m_Bounces; + int m_EvalTick; + int m_Owner; +}; + +#endif diff --git a/src/game/server/entities/laser.hpp b/src/game/server/entities/laser.hpp deleted file mode 100644 index aa4c2284..00000000 --- a/src/game/server/entities/laser.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#ifndef GAME_SERVER_ENTITY_LASER_H -#define GAME_SERVER_ENTITY_LASER_H - -#include <game/server/entity.hpp> - -class CHARACTER; - -class LASER : public ENTITY -{ - vec2 from; - vec2 dir; - float energy; - int bounces; - int eval_tick; - int owner; - - bool hit_character(vec2 from, vec2 to); - void do_bounce(); - -public: - - LASER(vec2 pos, vec2 direction, float start_energy, int owner); - - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; - -#endif diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index 436282cc..9798e2c3 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -1,143 +1,129 @@ -#include <engine/e_server_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/server/gamecontext.hpp> -#include "pickup.hpp" +#include <game/generated/protocol.h> +#include <game/server/gamecontext.h> +#include "pickup.h" -////////////////////////////////////////////////// -// pickup -////////////////////////////////////////////////// -PICKUP::PICKUP(int _type, int _subtype) -: ENTITY(NETOBJTYPE_PICKUP) +CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType) +: CEntity(pGameWorld, NETOBJTYPE_PICKUP) { - type = _type; - subtype = _subtype; - proximity_radius = phys_size; + m_Type = Type; + m_Subtype = SubType; + m_ProximityRadius = PickupPhysSize; - reset(); - - // TODO: should this be done here? - game.world.insert_entity(this); + Reset(); + + GameWorld()->InsertEntity(this); } -void PICKUP::reset() +void CPickup::Reset() { - if (data->pickups[type].spawndelay > 0) - spawntick = server_tick() + server_tickspeed() * data->pickups[type].spawndelay; + if (g_pData->m_aPickups[m_Type].m_Spawndelay > 0) + m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * g_pData->m_aPickups[m_Type].m_Spawndelay; else - spawntick = -1; + m_SpawnTick = -1; } -void PICKUP::tick() +void CPickup::Tick() { // wait for respawn - if(spawntick > 0) + if(m_SpawnTick > 0) { - if(server_tick() > spawntick) + if(Server()->Tick() > m_SpawnTick) { // respawn - spawntick = -1; + m_SpawnTick = -1; - if(type == POWERUP_WEAPON) - game.create_sound(pos, SOUND_WEAPON_SPAWN); + if(m_Type == POWERUP_WEAPON) + GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SPAWN); } else return; } // Check if a player intersected us - CHARACTER *chr = game.world.closest_character(pos, 20.0f, 0); - if(chr) + CCharacter *pChr = GameServer()->m_World.ClosestCharacter(m_Pos, 20.0f, 0); + if(pChr && pChr->IsAlive()) { // player picked us up, is someone was hooking us, let them go - int respawntime = -1; - switch (type) + int RespawnTime = -1; + switch (m_Type) { - case POWERUP_HEALTH: - if(chr->increase_health(1)) - { - game.create_sound(pos, SOUND_PICKUP_HEALTH); - respawntime = data->pickups[type].respawntime; - } - break; - case POWERUP_ARMOR: - if(chr->increase_armor(1)) - { - game.create_sound(pos, SOUND_PICKUP_ARMOR); - respawntime = data->pickups[type].respawntime; - } - break; + case POWERUP_HEALTH: + if(pChr->IncreaseHealth(1)) + { + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH); + RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; + } + break; + + case POWERUP_ARMOR: + if(pChr->IncreaseArmor(1)) + { + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR); + RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; + } + break; - case POWERUP_WEAPON: - if(subtype >= 0 && subtype < NUM_WEAPONS) - { - if(chr->weapons[subtype].ammo < data->weapons.id[subtype].maxammo || !chr->weapons[subtype].got) + case POWERUP_WEAPON: + if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS) { - chr->weapons[subtype].got = true; - chr->weapons[subtype].ammo = min(data->weapons.id[subtype].maxammo, chr->weapons[subtype].ammo + 10); - respawntime = data->pickups[type].respawntime; + if(pChr->GiveWeapon(m_Subtype, 10)) + { + RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; - // TODO: data compiler should take care of stuff like this - if(subtype == WEAPON_GRENADE) - game.create_sound(pos, SOUND_PICKUP_GRENADE); - else if(subtype == WEAPON_SHOTGUN) - game.create_sound(pos, SOUND_PICKUP_SHOTGUN); - else if(subtype == WEAPON_RIFLE) - game.create_sound(pos, SOUND_PICKUP_SHOTGUN); + if(m_Subtype == WEAPON_GRENADE) + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE); + else if(m_Subtype == WEAPON_SHOTGUN) + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); + else if(m_Subtype == WEAPON_RIFLE) + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN); - if(chr->player) - game.send_weapon_pickup(chr->player->client_id, subtype); + if(pChr->GetPlayer()) + GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype); + } } - } - break; - case POWERUP_NINJA: - { - // activate ninja on target player - chr->ninja.activationtick = server_tick(); - chr->weapons[WEAPON_NINJA].got = true; - chr->weapons[WEAPON_NINJA].ammo = -1; - chr->last_weapon = chr->active_weapon; - chr->active_weapon = WEAPON_NINJA; - respawntime = data->pickups[type].respawntime; - game.create_sound(pos, SOUND_PICKUP_NINJA); - - // loop through all players, setting their emotes - ENTITY *ents[64]; - int num = game.world.find_entities(vec2(0, 0), 1000000, ents, 64, NETOBJTYPE_CHARACTER); - for (int i = 0; i < num; i++) + break; + + case POWERUP_NINJA: { - CHARACTER *c = (CHARACTER *)ents[i]; - if (c != chr) + // activate ninja on target player + pChr->GiveNinja(); + RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; + + // loop through all players, setting their emotes + CEntity *apEnts[64]; + int Num = GameServer()->m_World.FindEntities(vec2(0, 0), 1000000, apEnts, 64, NETOBJTYPE_CHARACTER); + + for (int i = 0; i < Num; ++i) { - c->emote_type = EMOTE_SURPRISE; - c->emote_stop = server_tick() + server_tickspeed(); + CCharacter *pC = static_cast<CCharacter *>(apEnts[i]); + if (pC != pChr) + pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed()); } - } - chr->emote_type = EMOTE_ANGRY; - chr->emote_stop = server_tick() + 1200 * server_tickspeed() / 1000; + pChr->SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000); + break; + } + default: break; - } - default: - break; }; - if(respawntime >= 0) + if(RespawnTime >= 0) { dbg_msg("game", "pickup player='%d:%s' item=%d/%d", - chr->player->client_id, server_clientname(chr->player->client_id), type, subtype); - spawntick = server_tick() + server_tickspeed() * respawntime; + pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type, m_Subtype); + m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * RespawnTime; } } } -void PICKUP::snap(int snapping_client) +void CPickup::Snap(int SnappingClient) { - if(spawntick != -1) + if(m_SpawnTick != -1 || NetworkClipped(SnappingClient)) return; - NETOBJ_PICKUP *up = (NETOBJ_PICKUP *)snap_new_item(NETOBJTYPE_PICKUP, id, sizeof(NETOBJ_PICKUP)); - up->x = (int)pos.x; - up->y = (int)pos.y; - up->type = type; // TODO: two diffrent types? what gives? - up->subtype = subtype; + CNetObj_Pickup *pP = static_cast<CNetObj_Pickup *>(Server()->SnapNewItem(NETOBJTYPE_PICKUP, m_Id, sizeof(CNetObj_Pickup))); + pP->m_X = (int)m_Pos.x; + pP->m_Y = (int)m_Pos.y; + pP->m_Type = m_Type; + pP->m_Subtype = m_Subtype; } diff --git a/src/game/server/entities/pickup.h b/src/game/server/entities/pickup.h new file mode 100644 index 00000000..c076464c --- /dev/null +++ b/src/game/server/entities/pickup.h @@ -0,0 +1,23 @@ +#ifndef GAME_SERVER_ENTITIES_PICKUP_H +#define GAME_SERVER_ENTITIES_PICKUP_H + +#include <game/server/entity.h> + +const int PickupPhysSize = 14; + +class CPickup : public CEntity +{ +public: + CPickup(CGameWorld *pGameWorld, int Type, int SubType = 0); + + virtual void Reset(); + virtual void Tick(); + virtual void Snap(int SnappingClient); + +private: + int m_Type; + int m_Subtype; + int m_SpawnTick; +}; + +#endif diff --git a/src/game/server/entities/pickup.hpp b/src/game/server/entities/pickup.hpp deleted file mode 100644 index cd480d92..00000000 --- a/src/game/server/entities/pickup.hpp +++ /dev/null @@ -1,24 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#ifndef GAME_SERVER_ENTITY_PICKUP_H -#define GAME_SERVER_ENTITY_PICKUP_H - -#include <game/server/entity.hpp> - -// TODO: move to seperate file -class PICKUP : public ENTITY -{ -public: - static const int phys_size = 14; - - int type; - int subtype; // weapon type for instance? - int spawntick; - PICKUP(int _type, int _subtype = 0); - - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; - -#endif diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 2a8de766..18652ba1 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -1,105 +1,102 @@ -#include <engine/e_server_interface.h> -#include <game/generated/g_protocol.hpp> -#include <game/server/gamecontext.hpp> -#include "projectile.hpp" +#include <game/generated/protocol.h> +#include <game/server/gamecontext.h> +#include "projectile.h" - -////////////////////////////////////////////////// -// projectile -////////////////////////////////////////////////// -PROJECTILE::PROJECTILE(int type, int owner, vec2 pos, vec2 dir, int span, - int damage, int flags, float force, int sound_impact, int weapon) -: ENTITY(NETOBJTYPE_PROJECTILE) +CProjectile::CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span, + int Damage, bool Explosive, float Force, int SoundImpact, int Weapon) +: CEntity(pGameWorld, NETOBJTYPE_PROJECTILE) { - this->type = type; - this->pos = pos; - this->direction = dir; - this->lifespan = span; - this->owner = owner; - this->flags = flags; - this->force = force; - this->damage = damage; - this->sound_impact = sound_impact; - this->weapon = weapon; - this->bounce = 0; - this->start_tick = server_tick(); - game.world.insert_entity(this); + m_Type = Type; + m_Pos = Pos; + m_Direction = Dir; + m_LifeSpan = Span; + m_Owner = Owner; + m_Force = Force; + m_Damage = Damage; + m_SoundImpact = SoundImpact; + m_Weapon = Weapon; + m_StartTick = Server()->Tick(); + m_Explosive = Explosive; + + GameWorld()->InsertEntity(this); } -void PROJECTILE::reset() +void CProjectile::Reset() { - game.world.destroy_entity(this); + GameServer()->m_World.DestroyEntity(this); } -vec2 PROJECTILE::get_pos(float time) +vec2 CProjectile::GetPos(float Time) { - float curvature = 0; - float speed = 0; - if(type == WEAPON_GRENADE) - { - curvature = tuning.grenade_curvature; - speed = tuning.grenade_speed; - } - else if(type == WEAPON_SHOTGUN) - { - curvature = tuning.shotgun_curvature; - speed = tuning.shotgun_speed; - } - else if(type == WEAPON_GUN) + float Curvature = 0; + float Speed = 0; + + switch(m_Type) { - curvature = tuning.gun_curvature; - speed = tuning.gun_speed; + case WEAPON_GRENADE: + Curvature = GameServer()->Tuning()->m_GrenadeCurvature; + Speed = GameServer()->Tuning()->m_GrenadeSpeed; + break; + + case WEAPON_SHOTGUN: + Curvature = GameServer()->Tuning()->m_ShotgunCurvature; + Speed = GameServer()->Tuning()->m_ShotgunSpeed; + break; + + case WEAPON_GUN: + Curvature = GameServer()->Tuning()->m_GunCurvature; + Speed = GameServer()->Tuning()->m_GunSpeed; + break; } - return calc_pos(pos, direction, curvature, speed, time); + return CalcPos(m_Pos, m_Direction, Curvature, Speed, Time); } -void PROJECTILE::tick() +void CProjectile::Tick() { - - float pt = (server_tick()-start_tick-1)/(float)server_tickspeed(); - float ct = (server_tick()-start_tick)/(float)server_tickspeed(); - vec2 prevpos = get_pos(pt); - vec2 curpos = get_pos(ct); + float Pt = (Server()->Tick()-m_StartTick-1)/(float)Server()->TickSpeed(); + float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); + vec2 PrevPos = GetPos(Pt); + vec2 CurPos = GetPos(Ct); + int Collide = GameServer()->Collision()->IntersectLine(PrevPos, CurPos, &CurPos, 0); + CCharacter *OwnerChar = GameServer()->GetPlayerChar(m_Owner); + CCharacter *TargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, CurPos, 6.0f, CurPos, OwnerChar); - lifespan--; + m_LifeSpan--; - int collide = col_intersect_line(prevpos, curpos, &curpos, 0); - //int collide = col_check_point((int)curpos.x, (int)curpos.y); - CHARACTER *ownerchar = game.get_player_char(owner); - CHARACTER *targetchr = game.world.intersect_character(prevpos, curpos, 6.0f, curpos, ownerchar); - if(targetchr || collide || lifespan < 0) + if(TargetChr || Collide || m_LifeSpan < 0) { - if(lifespan >= 0 || weapon == WEAPON_GRENADE) - game.create_sound(curpos, sound_impact); + if(m_LifeSpan >= 0 || m_Weapon == WEAPON_GRENADE) + GameServer()->CreateSound(CurPos, m_SoundImpact); - if(flags & PROJECTILE_FLAGS_EXPLODE) - game.create_explosion(curpos, owner, weapon, false); - else if(targetchr) - targetchr->take_damage(direction * max(0.001f, force), damage, owner, weapon); + if(m_Explosive) + GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false); + + else if(TargetChr) + TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon); - game.world.destroy_entity(this); + GameServer()->m_World.DestroyEntity(this); } } -void PROJECTILE::fill_info(NETOBJ_PROJECTILE *proj) +void CProjectile::FillInfo(CNetObj_Projectile *pProj) { - proj->x = (int)pos.x; - proj->y = (int)pos.y; - proj->vx = (int)(direction.x*100.0f); - proj->vy = (int)(direction.y*100.0f); - proj->start_tick = start_tick; - proj->type = type; + pProj->m_X = (int)m_Pos.x; + pProj->m_Y = (int)m_Pos.y; + pProj->m_VelX = (int)(m_Direction.x*100.0f); + pProj->m_VelY = (int)(m_Direction.y*100.0f); + pProj->m_StartTick = m_StartTick; + pProj->m_Type = m_Type; } -void PROJECTILE::snap(int snapping_client) +void CProjectile::Snap(int SnappingClient) { - float ct = (server_tick()-start_tick)/(float)server_tickspeed(); + float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); - if(networkclipped(snapping_client, get_pos(ct))) + if(NetworkClipped(SnappingClient, GetPos(Ct))) return; - NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE)); - fill_info(proj); + CNetObj_Projectile *pProj = static_cast<CNetObj_Projectile *>(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, m_Id, sizeof(CNetObj_Projectile))); + FillInfo(pProj); } diff --git a/src/game/server/entities/projectile.h b/src/game/server/entities/projectile.h new file mode 100644 index 00000000..87f4f6c3 --- /dev/null +++ b/src/game/server/entities/projectile.h @@ -0,0 +1,30 @@ +#ifndef GAME_SERVER_ENTITIES_PROJECTILE_H +#define GAME_SERVER_ENTITIES_PROJECTILE_H + +class CProjectile : public CEntity +{ +public: + CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span, + int Damage, bool Explosive, float Force, int SoundImpact, int Weapon); + + vec2 GetPos(float Time); + void FillInfo(CNetObj_Projectile *pProj); + + virtual void Reset(); + virtual void Tick(); + virtual void Snap(int SnappingClient); + +private: + vec2 m_Direction; + int m_LifeSpan; + int m_Owner; + int m_Type; + int m_Damage; + int m_SoundImpact; + int m_Weapon; + float m_Force; + int m_StartTick; + bool m_Explosive; +}; + +#endif diff --git a/src/game/server/entities/projectile.hpp b/src/game/server/entities/projectile.hpp deleted file mode 100644 index a5c3b88f..00000000 --- a/src/game/server/entities/projectile.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#ifndef GAME_SERVER_ENTITY_PROJECTILE_H -#define GAME_SERVER_ENTITY_PROJECTILE_H - -class PROJECTILE : public ENTITY -{ -public: - enum - { - PROJECTILE_FLAGS_EXPLODE = 1 << 0, - }; - - vec2 direction; - int lifespan; - int owner; - int type; - int flags; - int damage; - int sound_impact; - int weapon; - int bounce; - float force; - int start_tick; - - PROJECTILE(int type, int owner, vec2 pos, vec2 vel, int span, - int damage, int flags, float force, int sound_impact, int weapon); - - vec2 get_pos(float time); - void fill_info(NETOBJ_PROJECTILE *proj); - - virtual void reset(); - virtual void tick(); - virtual void snap(int snapping_client); -}; - -#endif diff --git a/src/game/server/entity.cpp b/src/game/server/entity.cpp index 8e3345ab..d17c3fab 100644 --- a/src/game/server/entity.cpp +++ b/src/game/server/entity.cpp @@ -1,49 +1,50 @@ -#include <engine/e_server_interface.h> -#include "entity.hpp" -#include "gamecontext.hpp" +#include "entity.h" +#include "gamecontext.h" ////////////////////////////////////////////////// // Entity ////////////////////////////////////////////////// -ENTITY::ENTITY(int objtype) +CEntity::CEntity(CGameWorld *pGameWorld, int ObjType) { - this->objtype = objtype; - pos = vec2(0,0); - proximity_radius = 0; + m_pGameWorld = pGameWorld; + + m_Objtype = ObjType; + m_Pos = vec2(0,0); + m_ProximityRadius = 0; - marked_for_destroy = false; - id = snap_new_id(); + m_MarkedForDestroy = false; + m_Id = Server()->SnapNewID(); - next_entity = 0; - prev_entity = 0; - prev_type_entity = 0; - next_type_entity = 0; + m_pNextEntity = 0; + m_pPrevEntity = 0; + m_pPrevTypeEntity = 0; + m_pNextTypeEntity = 0; } -ENTITY::~ENTITY() +CEntity::~CEntity() { - game.world.remove_entity(this); - snap_free_id(id); + GameWorld()->RemoveEntity(this); + Server()->SnapFreeID(m_Id); } -int ENTITY::networkclipped(int snapping_client) +int CEntity::NetworkClipped(int SnappingClient) { - return networkclipped(snapping_client, pos); + return NetworkClipped(SnappingClient, m_Pos); } -int ENTITY::networkclipped(int snapping_client, vec2 check_pos) +int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos) { - if(snapping_client == -1) + if(SnappingClient == -1) return 0; - float dx = game.players[snapping_client]->view_pos.x-check_pos.x; - float dy = game.players[snapping_client]->view_pos.y-check_pos.y; + float dx = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.x-CheckPos.x; + float dy = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.y-CheckPos.y; - if(fabs(dx) > 1000.0f || fabs(dy) > 800.0f) + if(absolute(dx) > 1000.0f || absolute(dy) > 800.0f) return 1; - if(distance(game.players[snapping_client]->view_pos, check_pos) > 1100.0f) + if(distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, CheckPos) > 1100.0f) return 1; return 0; } diff --git a/src/game/server/entity.hpp b/src/game/server/entity.h index debe57b6..b7fd3d94 100644 --- a/src/game/server/entity.hpp +++ b/src/game/server/entity.h @@ -2,101 +2,109 @@ #define GAME_SERVER_ENTITY_H #include <new> -#include <base/vmath.hpp> +#include <base/vmath.h> +#include <game/server/gameworld.h> #define MACRO_ALLOC_HEAP() \ public: \ - void *operator new(size_t size) \ + void *operator new(size_t Size) \ { \ - void *p = mem_alloc(size, 1); \ + void *p = mem_alloc(Size, 1); \ /*dbg_msg("", "++ %p %d", p, size);*/ \ - mem_zero(p, size); \ + mem_zero(p, Size); \ return p; \ } \ - void operator delete(void *p) \ + void operator delete(void *pPtr) \ { \ /*dbg_msg("", "-- %p", p);*/ \ - mem_free(p); \ + mem_free(pPtr); \ } \ private: #define MACRO_ALLOC_POOL_ID() \ public: \ - void *operator new(size_t size, int id); \ + void *operator new(size_t Size, int id); \ void operator delete(void *p); \ private: -#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, poolsize) \ - static char pool_data_##POOLTYPE[poolsize][sizeof(POOLTYPE)] = {{0}}; \ - static int pool_used_##POOLTYPE[poolsize] = {0}; \ - void *POOLTYPE::operator new(size_t size, int id) \ +#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, PoolSize) \ + static char ms_PoolData##POOLTYPE[PoolSize][sizeof(POOLTYPE)] = {{0}}; \ + static int ms_PoolUsed##POOLTYPE[PoolSize] = {0}; \ + void *POOLTYPE::operator new(size_t Size, int id) \ { \ - dbg_assert(sizeof(POOLTYPE) == size, "size error"); \ - dbg_assert(!pool_used_##POOLTYPE[id], "already used"); \ + dbg_assert(sizeof(POOLTYPE) == Size, "size error"); \ + dbg_assert(!ms_PoolUsed##POOLTYPE[id], "already used"); \ /*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \ - pool_used_##POOLTYPE[id] = 1; \ - mem_zero(pool_data_##POOLTYPE[id], size); \ - return pool_data_##POOLTYPE[id]; \ + ms_PoolUsed##POOLTYPE[id] = 1; \ + mem_zero(ms_PoolData##POOLTYPE[id], Size); \ + return ms_PoolData##POOLTYPE[id]; \ } \ void POOLTYPE::operator delete(void *p) \ { \ - int id = (POOLTYPE*)p - (POOLTYPE*)pool_data_##POOLTYPE; \ - dbg_assert(pool_used_##POOLTYPE[id], "not used"); \ + int id = (POOLTYPE*)p - (POOLTYPE*)ms_PoolData##POOLTYPE; \ + dbg_assert(ms_PoolUsed##POOLTYPE[id], "not used"); \ /*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \ - pool_used_##POOLTYPE[id] = 0; \ - mem_zero(pool_data_##POOLTYPE[id], sizeof(POOLTYPE)); \ + ms_PoolUsed##POOLTYPE[id] = 0; \ + mem_zero(ms_PoolData##POOLTYPE[id], sizeof(POOLTYPE)); \ } /* Class: Entity Basic entity class. */ -class ENTITY +class CEntity { MACRO_ALLOC_HEAP() private: - friend class GAMEWORLD; // thy these? - ENTITY *prev_entity; - ENTITY *next_entity; + friend class CGameWorld; // thy these? + CEntity *m_pPrevEntity; + CEntity *m_pNextEntity; - ENTITY *prev_type_entity; - ENTITY *next_type_entity; + CEntity *m_pPrevTypeEntity; + CEntity *m_pNextTypeEntity; + + class CGameWorld *m_pGameWorld; protected: - bool marked_for_destroy; - int id; - int objtype; + bool m_MarkedForDestroy; + int m_Id; + int m_Objtype; public: - ENTITY(int objtype); - virtual ~ENTITY(); + CEntity(CGameWorld *pGameWorld, int Objtype); + virtual ~CEntity(); + + class CGameWorld *GameWorld() { return m_pGameWorld; } + class CGameContext *GameServer() { return GameWorld()->GameServer(); } + class IServer *Server() { return GameWorld()->Server(); } + - ENTITY *typenext() { return next_type_entity; } - ENTITY *typeprev() { return prev_type_entity; } + CEntity *TypeNext() { return m_pNextTypeEntity; } + CEntity *TypePrev() { return m_pPrevTypeEntity; } /* Function: destroy Destorys the entity. */ - virtual void destroy() { delete this; } + virtual void Destroy() { delete this; } /* Function: reset Called when the game resets the map. Puts the entity back to it's starting state or perhaps destroys it. */ - virtual void reset() {} + virtual void Reset() {} /* Function: tick Called progress the entity to the next tick. Updates and moves the entity to it's new state and position. */ - virtual void tick() {} + virtual void Tick() {} /* Function: tick_defered Called after all entities tick() function has been called. */ - virtual void tick_defered() {} + virtual void TickDefered() {} /* Function: snap @@ -109,7 +117,7 @@ public: snapshot of everything in the game for demo recording. */ - virtual void snap(int snapping_client) {} + virtual void Snap(int SnappingClient) {} /* Function: networkclipped(int snapping_client) @@ -125,21 +133,21 @@ public: Returns: Non-zero if the entity doesn't have to be in the snapshot. */ - int networkclipped(int snapping_client); - int networkclipped(int snapping_client, vec2 check_pos); + int NetworkClipped(int SnappingClient); + int NetworkClipped(int SnappingClient, vec2 CheckPos); /* Variable: proximity_radius Contains the physical size of the entity. */ - float proximity_radius; + float m_ProximityRadius; /* Variable: pos Contains the current posititon of the entity. */ - vec2 pos; + vec2 m_Pos; }; #endif diff --git a/src/game/server/eventhandler.cpp b/src/game/server/eventhandler.cpp index 761eaf2c..48b6689e 100644 --- a/src/game/server/eventhandler.cpp +++ b/src/game/server/eventhandler.cpp @@ -1,48 +1,54 @@ -#include "eventhandler.hpp" -#include "gamecontext.hpp" +#include "eventhandler.h" +#include "gamecontext.h" ////////////////////////////////////////////////// // Event handler ////////////////////////////////////////////////// -EVENTHANDLER::EVENTHANDLER() +CEventHandler::CEventHandler() { - clear(); + m_pGameServer = 0; + Clear(); } -void *EVENTHANDLER::create(int type, int size, int mask) +void CEventHandler::SetGameServer(CGameContext *pGameServer) { - if(num_events == MAX_EVENTS) + m_pGameServer = pGameServer; +} + +void *CEventHandler::Create(int Type, int Size, int Mask) +{ + if(m_NumEvents == MAX_EVENTS) return 0; - if(current_offset+size >= MAX_DATASIZE) + if(m_CurrentOffset+Size >= MAX_DATASIZE) return 0; - void *p = &data[current_offset]; - offsets[num_events] = current_offset; - types[num_events] = type; - sizes[num_events] = size; - client_masks[num_events] = mask; - current_offset += size; - num_events++; + void *p = &m_aData[m_CurrentOffset]; + m_aOffsets[m_NumEvents] = m_CurrentOffset; + m_aTypes[m_NumEvents] = Type; + m_aSizes[m_NumEvents] = Size; + m_aClientMasks[m_NumEvents] = Mask; + m_CurrentOffset += Size; + m_NumEvents++; return p; } -void EVENTHANDLER::clear() +void CEventHandler::Clear() { - num_events = 0; - current_offset = 0; + m_NumEvents = 0; + m_CurrentOffset = 0; } -void EVENTHANDLER::snap(int snapping_client) +void CEventHandler::Snap(int SnappingClient) { - for(int i = 0; i < num_events; i++) + for(int i = 0; i < m_NumEvents; i++) { - if(snapping_client == -1 || cmask_is_set(client_masks[i], snapping_client)) + if(SnappingClient == -1 || CmaskIsSet(m_aClientMasks[i], SnappingClient)) { - NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&data[offsets[i]]; - if(snapping_client == -1 || distance(game.players[snapping_client]->view_pos, vec2(ev->x, ev->y)) < 1500.0f) + NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&m_aData[m_aOffsets[i]]; + if(SnappingClient == -1 || distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, vec2(ev->m_X, ev->m_Y)) < 1500.0f) { - void *d = snap_new_item(types[i], i, sizes[i]); - mem_copy(d, &data[offsets[i]], sizes[i]); + void *d = GameServer()->Server()->SnapNewItem(m_aTypes[i], i, m_aSizes[i]); + mem_copy(d, &m_aData[m_aOffsets[i]], m_aSizes[i]); } } } diff --git a/src/game/server/eventhandler.h b/src/game/server/eventhandler.h new file mode 100644 index 00000000..3833efe0 --- /dev/null +++ b/src/game/server/eventhandler.h @@ -0,0 +1,30 @@ +#ifndef GAME_SERVER_EVENTHANDLER_H +#define GAME_SERVER_EVENTHANDLER_H + +// +class CEventHandler +{ + static const int MAX_EVENTS = 128; + static const int MAX_DATASIZE = 128*64; + + int m_aTypes[MAX_EVENTS]; // TODO: remove some of these arrays + int m_aOffsets[MAX_EVENTS]; + int m_aSizes[MAX_EVENTS]; + int m_aClientMasks[MAX_EVENTS]; + char m_aData[MAX_DATASIZE]; + + class CGameContext *m_pGameServer; + + int m_CurrentOffset; + int m_NumEvents; +public: + CGameContext *GameServer() const { return m_pGameServer; } + void SetGameServer(CGameContext *pGameServer); + + CEventHandler(); + void *Create(int Type, int Size, int Mask = -1); + void Clear(); + void Snap(int SnappingClient); +}; + +#endif diff --git a/src/game/server/eventhandler.hpp b/src/game/server/eventhandler.hpp deleted file mode 100644 index 4d513154..00000000 --- a/src/game/server/eventhandler.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef GAME_SERVER_EVENTHANDLER_H -#define GAME_SERVER_EVENTHANDLER_H - -// -class EVENTHANDLER -{ - static const int MAX_EVENTS = 128; - static const int MAX_DATASIZE = 128*64; - - int types[MAX_EVENTS]; // TODO: remove some of these arrays - int offsets[MAX_EVENTS]; - int sizes[MAX_EVENTS]; - int client_masks[MAX_EVENTS]; - char data[MAX_DATASIZE]; - - int current_offset; - int num_events; -public: - EVENTHANDLER(); - void *create(int type, int size, int mask = -1); - void clear(); - void snap(int snapping_client); -}; - -#endif diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 736d437f..795bb65f 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1,99 +1,143 @@ -#include <string.h> #include <new> -#include <engine/e_server_interface.h> -#include "gamecontext.hpp" +#include <base/math.h> +#include <engine/shared/config.h> +#include <engine/map.h> +#include <engine/console.h> +#include "gamecontext.h" +#include <game/version.h> +#include <game/collision.h> +#include <game/gamecore.h> +#include "gamemodes/dm.h" +#include "gamemodes/tdm.h" +#include "gamemodes/ctf.h" +#include "gamemodes/mod.h" -GAMECONTEXT game; +enum +{ + RESET, + NO_RESET +}; -GAMECONTEXT::GAMECONTEXT() +void CGameContext::Construct(int Resetting) { + m_Resetting = 0; + m_pServer = 0; + for(int i = 0; i < MAX_CLIENTS; i++) - players[i] = 0; + m_apPlayers[i] = 0; - controller = 0; - vote_closetime = 0; + m_pController = 0; + m_VoteCloseTime = 0; + m_pVoteOptionFirst = 0; + m_pVoteOptionLast = 0; + + if(Resetting==NO_RESET) + m_pVoteOptionHeap = new CHeap(); +} + +CGameContext::CGameContext(int Resetting) +{ + Construct(Resetting); +} + +CGameContext::CGameContext() +{ + Construct(NO_RESET); } -GAMECONTEXT::~GAMECONTEXT() +CGameContext::~CGameContext() { for(int i = 0; i < MAX_CLIENTS; i++) - delete players[i]; + delete m_apPlayers[i]; + if(!m_Resetting) + delete m_pVoteOptionHeap; } -void GAMECONTEXT::clear() +void CGameContext::Clear() { - this->~GAMECONTEXT(); + CHeap *pVoteOptionHeap = m_pVoteOptionHeap; + CVoteOption *pVoteOptionFirst = m_pVoteOptionFirst; + CVoteOption *pVoteOptionLast = m_pVoteOptionLast; + CTuningParams Tuning = m_Tuning; + + m_Resetting = true; + this->~CGameContext(); mem_zero(this, sizeof(*this)); - new (this) GAMECONTEXT(); + new (this) CGameContext(RESET); + + m_pVoteOptionHeap = pVoteOptionHeap; + m_pVoteOptionFirst = pVoteOptionFirst; + m_pVoteOptionLast = pVoteOptionLast; + m_Tuning = Tuning; } -class CHARACTER *GAMECONTEXT::get_player_char(int client_id) +class CCharacter *CGameContext::GetPlayerChar(int ClientId) { - if(client_id < 0 || client_id >= MAX_CLIENTS || !players[client_id]) + if(ClientId < 0 || ClientId >= MAX_CLIENTS || !m_apPlayers[ClientId]) return 0; - return players[client_id]->get_character(); + return m_apPlayers[ClientId]->GetCharacter(); } -void GAMECONTEXT::create_damageind(vec2 p, float angle, int amount) +void CGameContext::CreateDamageInd(vec2 p, float Angle, int Amount) { - float a = 3 * 3.14159f / 2 + angle; + float a = 3 * 3.14159f / 2 + Angle; //float a = get_angle(dir); float s = a-pi/3; float e = a+pi/3; - for(int i = 0; i < amount; i++) + for(int i = 0; i < Amount; i++) { - float f = mix(s, e, float(i+1)/float(amount+2)); - NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)events.create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND)); + float f = mix(s, e, float(i+1)/float(Amount+2)); + NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND)); if(ev) { - ev->x = (int)p.x; - ev->y = (int)p.y; - ev->angle = (int)(f*256.0f); + ev->m_X = (int)p.x; + ev->m_Y = (int)p.y; + ev->m_Angle = (int)(f*256.0f); } } } -void GAMECONTEXT::create_hammerhit(vec2 p) +void CGameContext::CreateHammerHit(vec2 p) { // create the event - NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)events.create(NETEVENTTYPE_HAMMERHIT, sizeof(NETEVENT_HAMMERHIT)); + NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(NETEVENT_HAMMERHIT)); if(ev) { - ev->x = (int)p.x; - ev->y = (int)p.y; + ev->m_X = (int)p.x; + ev->m_Y = (int)p.y; } } -void GAMECONTEXT::create_explosion(vec2 p, int owner, int weapon, bool bnodamage) +void CGameContext::CreateExplosion(vec2 p, int Owner, int Weapon, bool NoDamage) { // create the event - NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)events.create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION)); + NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION)); if(ev) { - ev->x = (int)p.x; - ev->y = (int)p.y; + ev->m_X = (int)p.x; + ev->m_Y = (int)p.y; } - if (!bnodamage) + if (!NoDamage) { // deal damage - CHARACTER *ents[64]; - float radius = 135.0f; - float innerradius = 48.0f; - int num = game.world.find_entities(p, radius, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER); - for(int i = 0; i < num; i++) + CCharacter *apEnts[64]; + float Radius = 135.0f; + float InnerRadius = 48.0f; + int Num = m_World.FindEntities(p, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER); + for(int i = 0; i < Num; i++) { - vec2 diff = ents[i]->pos - p; - vec2 forcedir(0,1); - float l = length(diff); + vec2 Diff = apEnts[i]->m_Pos - p; + vec2 ForceDir(0,1); + float l = length(Diff); if(l) - forcedir = normalize(diff); - l = 1-clamp((l-innerradius)/(radius-innerradius), 0.0f, 1.0f); - float dmg = 6 * l; - if((int)dmg) - ents[i]->take_damage(forcedir*dmg*2, (int)dmg, owner, weapon); + ForceDir = normalize(Diff); + l = 1-clamp((l-InnerRadius)/(Radius-InnerRadius), 0.0f, 1.0f); + float Dmg = 6 * l; + if((int)Dmg) + apEnts[i]->TakeDamage(ForceDir*Dmg*2, (int)Dmg, Owner, Weapon); } } } @@ -110,273 +154,893 @@ void create_smoke(vec2 p) } }*/ -void GAMECONTEXT::create_playerspawn(vec2 p) +void CGameContext::CreatePlayerSpawn(vec2 p) { // create the event - NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)events.create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN)); + NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN)); if(ev) { - ev->x = (int)p.x; - ev->y = (int)p.y; + ev->m_X = (int)p.x; + ev->m_Y = (int)p.y; } } -void GAMECONTEXT::create_death(vec2 p, int cid) +void CGameContext::CreateDeath(vec2 p, int ClientId) { // create the event - NETEVENT_DEATH *ev = (NETEVENT_DEATH *)events.create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH)); + NETEVENT_DEATH *ev = (NETEVENT_DEATH *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH)); if(ev) { - ev->x = (int)p.x; - ev->y = (int)p.y; - ev->cid = cid; + ev->m_X = (int)p.x; + ev->m_Y = (int)p.y; + ev->m_ClientId = ClientId; } } -void GAMECONTEXT::create_sound(vec2 pos, int sound, int mask) +void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask) { - if (sound < 0) + if (Sound < 0) return; // create a sound - NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)events.create(NETEVENTTYPE_SOUNDWORLD, sizeof(NETEVENT_SOUNDWORLD), mask); + NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(NETEVENT_SOUNDWORLD), Mask); if(ev) { - ev->x = (int)pos.x; - ev->y = (int)pos.y; - ev->soundid = sound; + ev->m_X = (int)Pos.x; + ev->m_Y = (int)Pos.y; + ev->m_SoundId = Sound; } } -void GAMECONTEXT::create_sound_global(int sound, int target) +void CGameContext::CreateSoundGlobal(int Sound, int Target) { - if (sound < 0) + if (Sound < 0) return; - NETMSG_SV_SOUNDGLOBAL msg; - msg.soundid = sound; - msg.pack(MSGFLAG_VITAL); - server_send_msg(target); + CNetMsg_Sv_SoundGlobal Msg; + Msg.m_Soundid = Sound; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, Target); } -void GAMECONTEXT::send_chat_target(int to, const char *text) +void CGameContext::SendChatTarget(int To, const char *pText) { - NETMSG_SV_CHAT msg; - msg.team = 0; - msg.cid = -1; - msg.message = text; - msg.pack(MSGFLAG_VITAL); - server_send_msg(to); + CNetMsg_Sv_Chat Msg; + Msg.m_Team = 0; + Msg.m_Cid = -1; + Msg.m_pMessage = pText; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, To); } -void GAMECONTEXT::send_chat(int chatter_cid, int team, const char *text) +void CGameContext::SendChat(int ChatterClientId, int Team, const char *pText) { - if(chatter_cid >= 0 && chatter_cid < MAX_CLIENTS) - dbg_msg("chat", "%d:%d:%s: %s", chatter_cid, team, server_clientname(chatter_cid), text); + if(ChatterClientId >= 0 && ChatterClientId < MAX_CLIENTS) + dbg_msg("chat", "%d:%d:%s: %s", ChatterClientId, Team, Server()->ClientName(ChatterClientId), pText); else - dbg_msg("chat", "*** %s", text); + dbg_msg("chat", "*** %s", pText); - if(team == CHAT_ALL) + if(Team == CHAT_ALL) { - NETMSG_SV_CHAT msg; - msg.team = 0; - msg.cid = chatter_cid; - msg.message = text; - msg.pack(MSGFLAG_VITAL); - server_send_msg(-1); + CNetMsg_Sv_Chat Msg; + Msg.m_Team = 0; + Msg.m_Cid = ChatterClientId; + Msg.m_pMessage = pText; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1); } else { - NETMSG_SV_CHAT msg; - msg.team = 1; - msg.cid = chatter_cid; - msg.message = text; + CNetMsg_Sv_Chat Msg; + Msg.m_Team = 1; + Msg.m_Cid = ChatterClientId; + Msg.m_pMessage = pText; // pack one for the recording only - msg.pack(MSGFLAG_VITAL|MSGFLAG_NOSEND); - server_send_msg(-1); + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NOSEND, -1); // send to the clients - msg.pack(MSGFLAG_VITAL|MSGFLAG_NORECORD); for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i] && game.players[i]->team == team) - server_send_msg(i); + if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() == Team) + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i); } } } -void GAMECONTEXT::send_emoticon(int cid, int emoticon) +void CGameContext::SendEmoticon(int ClientId, int Emoticon) { - NETMSG_SV_EMOTICON msg; - msg.cid = cid; - msg.emoticon = emoticon; - msg.pack(MSGFLAG_VITAL); - server_send_msg(-1); + CNetMsg_Sv_Emoticon Msg; + Msg.m_Cid = ClientId; + Msg.m_Emoticon = Emoticon; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1); } -void GAMECONTEXT::send_weapon_pickup(int cid, int weapon) +void CGameContext::SendWeaponPickup(int ClientId, int Weapon) { - NETMSG_SV_WEAPONPICKUP msg; - msg.weapon = weapon; - msg.pack(MSGFLAG_VITAL); - server_send_msg(cid); + CNetMsg_Sv_WeaponPickup Msg; + Msg.m_Weapon = Weapon; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId); } -void GAMECONTEXT::send_broadcast(const char *text, int cid) +void CGameContext::SendBroadcast(const char *pText, int ClientId) { - NETMSG_SV_BROADCAST msg; - msg.message = text; - msg.pack(MSGFLAG_VITAL); - server_send_msg(cid); + CNetMsg_Sv_Broadcast Msg; + Msg.m_pMessage = pText; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId); } // -void GAMECONTEXT::start_vote(const char *desc, const char *command) +void CGameContext::StartVote(const char *pDesc, const char *pCommand) { // check if a vote is already running - if(vote_closetime) + if(m_VoteCloseTime) return; // reset votes - vote_enforce = VOTE_ENFORCE_UNKNOWN; + m_VoteEnforce = VOTE_ENFORCE_UNKNOWN; for(int i = 0; i < MAX_CLIENTS; i++) { - if(players[i]) - players[i]->vote = 0; + if(m_apPlayers[i]) + { + m_apPlayers[i]->m_Vote = 0; + m_apPlayers[i]->m_VotePos = 0; + } } // start vote - vote_closetime = time_get() + time_freq()*25; - str_copy(vote_description, desc, sizeof(vote_description)); - str_copy(vote_command, command, sizeof(vote_description)); - send_vote_set(-1); - send_vote_status(-1); + m_VoteCloseTime = time_get() + time_freq()*25; + str_copy(m_aVoteDescription, pDesc, sizeof(m_aVoteDescription)); + str_copy(m_aVoteCommand, pCommand, sizeof(m_aVoteCommand)); + SendVoteSet(-1); + m_VoteUpdate = true; } -void GAMECONTEXT::end_vote() +void CGameContext::EndVote() { - vote_closetime = 0; - send_vote_set(-1); + m_VoteCloseTime = 0; + SendVoteSet(-1); } -void GAMECONTEXT::send_vote_set(int cid) +void CGameContext::SendVoteSet(int ClientId) { - NETMSG_SV_VOTE_SET msg; - if(vote_closetime) + CNetMsg_Sv_VoteSet Msg; + if(m_VoteCloseTime) { - msg.timeout = (vote_closetime-time_get())/time_freq(); - msg.description = vote_description; - msg.command = vote_command; + Msg.m_Timeout = (m_VoteCloseTime-time_get())/time_freq(); + Msg.m_pDescription = m_aVoteDescription; + Msg.m_pCommand = ""; } else { - msg.timeout = 0; - msg.description = ""; - msg.command = ""; + Msg.m_Timeout = 0; + Msg.m_pDescription = ""; + Msg.m_pCommand = ""; } - msg.pack(MSGFLAG_VITAL); - server_send_msg(cid); + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId); } -void GAMECONTEXT::send_vote_status(int cid) +void CGameContext::SendVoteStatus(int ClientId, int Total, int Yes, int No) { - NETMSG_SV_VOTE_STATUS msg = {0}; - for(int i = 0; i < MAX_CLIENTS; i++) + CNetMsg_Sv_VoteStatus Msg = {0}; + Msg.m_Total = Total; + Msg.m_Yes = Yes; + Msg.m_No = No; + Msg.m_Pass = Total - (Yes+No); + + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId); + +} + +void CGameContext::AbortVoteKickOnDisconnect(int ClientId) +{ + if(m_VoteCloseTime && !str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientId) + m_VoteCloseTime = -1; +} + + +void CGameContext::CheckPureTuning() +{ + // might not be created yet during start up + if(!m_pController) + return; + + if( str_comp(m_pController->m_pGameType, "DM")==0 || + str_comp(m_pController->m_pGameType, "TDM")==0 || + str_comp(m_pController->m_pGameType, "CTF")==0) { - if(players[i]) + CTuningParams p; + if(mem_comp(&p, &m_Tuning, sizeof(p)) != 0) { - msg.total++; - if(players[i]->vote > 0) - msg.yes++; - else if(players[i]->vote < 0) - msg.no++; - else - msg.pass++; + dbg_msg("server", "resetting tuning due to pure server"); + m_Tuning = p; } } - - msg.pack(MSGFLAG_VITAL); - server_send_msg(cid); - } -void GAMECONTEXT::abort_vote_kick_on_disconnect(int client_id) +void CGameContext::SendTuningParams(int Cid) { - if(vote_closetime && !strncmp(vote_command, "kick ", 5) && atoi(&vote_command[5]) == client_id) - vote_closetime = -1; + CheckPureTuning(); + + CMsgPacker Msg(NETMSGTYPE_SV_TUNEPARAMS); + int *pParams = (int *)&m_Tuning; + for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++) + Msg.AddInt(pParams[i]); + Server()->SendMsg(&Msg, MSGFLAG_VITAL, Cid); } -void GAMECONTEXT::tick() +void CGameContext::OnTick() { - world.core.tuning = tuning; - world.tick(); + // check tuning + CheckPureTuning(); + + // copy tuning + m_World.m_Core.m_Tuning = m_Tuning; + m_World.Tick(); //if(world.paused) // make sure that the game object always updates - controller->tick(); + m_pController->Tick(); for(int i = 0; i < MAX_CLIENTS; i++) { - if(players[i]) - players[i]->tick(); + if(m_apPlayers[i]) + m_apPlayers[i]->Tick(); } // update voting - if(vote_closetime) + if(m_VoteCloseTime) { // abort the kick-vote on player-leave - if(vote_closetime == -1) + if(m_VoteCloseTime == -1) { - send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote aborted"); - end_vote(); + SendChat(-1, CGameContext::CHAT_ALL, "Vote aborted"); + EndVote(); } else { - // count votes - int total = 0, yes = 0, no = 0; - for(int i = 0; i < MAX_CLIENTS; i++) + int Total = 0, Yes = 0, No = 0; + if(m_VoteUpdate) { - if(players[i]) + // count votes + char aaBuf[MAX_CLIENTS][64] = {{0}}; + for(int i = 0; i < MAX_CLIENTS; i++) + if(m_apPlayers[i]) + Server()->GetClientIP(i, aaBuf[i], 64); + bool aVoteChecked[MAX_CLIENTS] = {0}; + for(int i = 0; i < MAX_CLIENTS; i++) { - total++; - if(players[i]->vote > 0) - yes++; - else if(players[i]->vote < 0) - no++; + if(!m_apPlayers[i] || m_apPlayers[i]->GetTeam() == -1 || aVoteChecked[i]) // don't count in votes by spectators + continue; + + int ActVote = m_apPlayers[i]->m_Vote; + int ActVotePos = m_apPlayers[i]->m_VotePos; + + // check for more players with the same ip (only use the vote of the one who voted first) + for(int j = i+1; j < MAX_CLIENTS; ++j) + { + if(!m_apPlayers[j] || aVoteChecked[j] || str_comp(aaBuf[j], aaBuf[i])) + continue; + + aVoteChecked[j] = true; + if(m_apPlayers[j]->m_Vote && (!ActVote || ActVotePos > m_apPlayers[j]->m_VotePos)) + { + ActVote = m_apPlayers[j]->m_Vote; + ActVotePos = m_apPlayers[j]->m_VotePos; + } + } + + Total++; + if(ActVote > 0) + Yes++; + else if(ActVote < 0) + No++; } + + if(Yes >= Total/2+1) + m_VoteEnforce = VOTE_ENFORCE_YES; + else if(No >= Total/2+1 || Yes+No == Total) + m_VoteEnforce = VOTE_ENFORCE_NO; } + + if(m_VoteEnforce == VOTE_ENFORCE_YES) + { + Console()->ExecuteLine(m_aVoteCommand); + EndVote(); + SendChat(-1, CGameContext::CHAT_ALL, "Vote passed"); + + if(m_apPlayers[m_VoteCreator]) + m_apPlayers[m_VoteCreator]->m_Last_VoteCall = 0; + } + else if(m_VoteEnforce == VOTE_ENFORCE_NO || time_get() > m_VoteCloseTime) + { + EndVote(); + SendChat(-1, CGameContext::CHAT_ALL, "Vote failed"); + } + else if(m_VoteUpdate) + { + m_VoteUpdate = false; + SendVoteStatus(-1, Total, Yes, No); + } + } + } + + +#ifdef CONF_DEBUG + if(g_Config.m_DbgDummies) + { + for(int i = 0; i < g_Config.m_DbgDummies ; i++) + { + CNetObj_PlayerInput Input = {0}; + Input.m_Direction = (i&1)?-1:1; + m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input); + } + } +#endif +} + +// Server hooks +void CGameContext::OnClientDirectInput(int ClientID, void *pInput) +{ + if(!m_World.m_Paused) + m_apPlayers[ClientID]->OnDirectInput((CNetObj_PlayerInput *)pInput); +} + +void CGameContext::OnClientPredictedInput(int ClientID, void *pInput) +{ + if(!m_World.m_Paused) + m_apPlayers[ClientID]->OnPredictedInput((CNetObj_PlayerInput *)pInput); +} + +void CGameContext::OnClientEnter(int ClientId) +{ + //world.insert_entity(&players[client_id]); + m_apPlayers[ClientId]->Respawn(); + dbg_msg("game", "join player='%d:%s'", ClientId, Server()->ClientName(ClientId)); + + + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "%s entered and joined the %s", Server()->ClientName(ClientId), m_pController->GetTeamName(m_apPlayers[ClientId]->GetTeam())); + SendChat(-1, CGameContext::CHAT_ALL, aBuf); + + dbg_msg("game", "team_join player='%d:%s' team=%d", ClientId, Server()->ClientName(ClientId), m_apPlayers[ClientId]->GetTeam()); + + m_VoteUpdate = true; +} + +void CGameContext::OnClientConnected(int ClientId) +{ + // Check which team the player should be on + const int StartTeam = g_Config.m_SvTournamentMode ? -1 : m_pController->GetAutoTeam(ClientId); + + m_apPlayers[ClientId] = new(ClientId) CPlayer(this, ClientId, StartTeam); + //players[client_id].init(client_id); + //players[client_id].client_id = client_id; + + (void)m_pController->CheckTeamBalance(); + +#ifdef CONF_DEBUG + if(g_Config.m_DbgDummies) + { + if(ClientId >= MAX_CLIENTS-g_Config.m_DbgDummies) + return; + } +#endif + + // send active vote + if(m_VoteCloseTime) + SendVoteSet(ClientId); + + // send motd + CNetMsg_Sv_Motd Msg; + Msg.m_pMessage = g_Config.m_SvMotd; + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId); +} + +void CGameContext::OnClientDrop(int ClientId) +{ + AbortVoteKickOnDisconnect(ClientId); + m_apPlayers[ClientId]->OnDisconnect(); + delete m_apPlayers[ClientId]; + m_apPlayers[ClientId] = 0; + + (void)m_pController->CheckTeamBalance(); + m_VoteUpdate = true; +} + +void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId) +{ + void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); + CPlayer *p = m_apPlayers[ClientId]; + + if(!pRawMsg) + { + dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn()); + return; + } + + if(MsgId == NETMSGTYPE_CL_SAY) + { + CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg; + int Team = pMsg->m_Team; + if(Team) + Team = p->GetTeam(); + else + Team = CGameContext::CHAT_ALL; + + if(g_Config.m_SvSpamprotection && p->m_Last_Chat && p->m_Last_Chat+Server()->TickSpeed() > Server()->Tick()) + return; + + p->m_Last_Chat = Server()->Tick(); + + // check for invalid chars + unsigned char *pMessage = (unsigned char *)pMsg->m_pMessage; + while (*pMessage) + { + if(*pMessage < 32) + *pMessage = ' '; + pMessage++; + } + + SendChat(ClientId, Team, pMsg->m_pMessage); + } + else if(MsgId == NETMSGTYPE_CL_CALLVOTE) + { + if(g_Config.m_SvSpamprotection && p->m_Last_VoteTry && p->m_Last_VoteTry+Server()->TickSpeed()*3 > Server()->Tick()) + return; + + int64 Now = Server()->Tick(); + p->m_Last_VoteTry = Now; + if(m_VoteCloseTime) + { + SendChatTarget(ClientId, "Wait for current vote to end before calling a new one."); + return; + } - if(vote_enforce == VOTE_ENFORCE_YES || yes >= total/2+1) + int Timeleft = p->m_Last_VoteCall + Server()->TickSpeed()*60 - Now; + if(p->m_Last_VoteCall && Timeleft > 0) + { + char aChatmsg[512] = {0}; + str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d seconds before making another vote", (Timeleft/Server()->TickSpeed())+1); + SendChatTarget(ClientId, aChatmsg); + return; + } + + char aChatmsg[512] = {0}; + char aDesc[512] = {0}; + char aCmd[512] = {0}; + CNetMsg_Cl_CallVote *pMsg = (CNetMsg_Cl_CallVote *)pRawMsg; + if(str_comp_nocase(pMsg->m_Type, "option") == 0) + { + CVoteOption *pOption = m_pVoteOptionFirst; + while(pOption) { - console_execute_line(vote_command); - end_vote(); - send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote passed"); + if(str_comp_nocase(pMsg->m_Value, pOption->m_aCommand) == 0) + { + str_format(aChatmsg, sizeof(aChatmsg), "%s called vote to change server option '%s'", Server()->ClientName(ClientId), pOption->m_aCommand); + str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aCommand); + str_format(aCmd, sizeof(aCmd), "%s", pOption->m_aCommand); + break; + } + + pOption = pOption->m_pNext; + } - if(players[vote_creator]) - players[vote_creator]->last_votecall = 0; + if(!pOption) + { + str_format(aChatmsg, sizeof(aChatmsg), "'%s' isn't an option on this server", pMsg->m_Value); + SendChatTarget(ClientId, aChatmsg); + return; } - else if(vote_enforce == VOTE_ENFORCE_NO || time_get() > vote_closetime || no >= total/2+1 || yes+no == total) + } + else if(str_comp_nocase(pMsg->m_Type, "kick") == 0) + { + if(!g_Config.m_SvVoteKick) { - end_vote(); - send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote failed"); + SendChatTarget(ClientId, "Server does not allow voting to kick players"); + return; } + + int KickId = str_toint(pMsg->m_Value); + if(KickId < 0 || KickId >= MAX_CLIENTS || !m_apPlayers[KickId]) + { + SendChatTarget(ClientId, "Invalid client id to kick"); + return; + } + + str_format(aChatmsg, sizeof(aChatmsg), "%s called for vote to kick '%s'", Server()->ClientName(ClientId), Server()->ClientName(KickId)); + str_format(aDesc, sizeof(aDesc), "Kick '%s'", Server()->ClientName(KickId)); + if (!g_Config.m_SvVoteKickBantime) + str_format(aCmd, sizeof(aCmd), "kick %d", KickId); + else + { + char aBuf[64] = {0}; + Server()->GetClientIP(KickId, aBuf, sizeof(aBuf)); + str_format(aCmd, sizeof(aCmd), "ban %s %d", aBuf, g_Config.m_SvVoteKickBantime); + } + } + + if(aCmd[0]) + { + SendChat(-1, CGameContext::CHAT_ALL, aChatmsg); + StartVote(aDesc, aCmd); + p->m_Vote = 1; + p->m_VotePos = m_VotePos = 1; + m_VoteCreator = ClientId; + p->m_Last_VoteCall = Now; + } + } + else if(MsgId == NETMSGTYPE_CL_VOTE) + { + if(!m_VoteCloseTime) + return; + + if(p->m_Vote == 0) + { + CNetMsg_Cl_Vote *pMsg = (CNetMsg_Cl_Vote *)pRawMsg; + if(!pMsg->m_Vote) + return; + + p->m_Vote = pMsg->m_Vote; + p->m_VotePos = ++m_VotePos; + m_VoteUpdate = true; } } + else if (MsgId == NETMSGTYPE_CL_SETTEAM && !m_World.m_Paused) + { + CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg; + + if(p->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && p->m_Last_SetTeam && p->m_Last_SetTeam+Server()->TickSpeed()*3 > Server()->Tick())) + return; + + // Switch team on given client and kill/respawn him + if(m_pController->CanJoinTeam(pMsg->m_Team, ClientId)) + { + if(m_pController->CanChangeTeam(p, pMsg->m_Team)) + { + p->m_Last_SetTeam = Server()->Tick(); + if(p->GetTeam() == -1 || pMsg->m_Team == -1) + m_VoteUpdate = true; + p->SetTeam(pMsg->m_Team); + (void)m_pController->CheckTeamBalance(); + } + else + SendBroadcast("Teams must be balanced, please join other team", ClientId); + } + else + { + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots); + SendBroadcast(aBuf, ClientId); + } + } + else if (MsgId == NETMSGTYPE_CL_CHANGEINFO || MsgId == NETMSGTYPE_CL_STARTINFO) + { + CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg; + + if(g_Config.m_SvSpamprotection && p->m_Last_ChangeInfo && p->m_Last_ChangeInfo+Server()->TickSpeed()*5 > Server()->Tick()) + return; + + p->m_Last_ChangeInfo = Server()->Tick(); + + p->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor; + p->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody; + p->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet; + + // check for invalid chars + unsigned char *pName = (unsigned char *)pMsg->m_pName; + while (*pName) + { + if(*pName < 32) + *pName = ' '; + pName++; + } + + // copy old name + char aOldName[MAX_NAME_LENGTH]; + str_copy(aOldName, Server()->ClientName(ClientId), MAX_NAME_LENGTH); + + Server()->SetClientName(ClientId, pMsg->m_pName); + if(MsgId == NETMSGTYPE_CL_CHANGEINFO && str_comp(aOldName, Server()->ClientName(ClientId)) != 0) + { + char aChatText[256]; + str_format(aChatText, sizeof(aChatText), "%s changed name to %s", aOldName, Server()->ClientName(ClientId)); + SendChat(-1, CGameContext::CHAT_ALL, aChatText); + } + + // set skin + str_copy(p->m_TeeInfos.m_SkinName, pMsg->m_pSkin, sizeof(p->m_TeeInfos.m_SkinName)); + + m_pController->OnPlayerInfoChange(p); + + if(MsgId == NETMSGTYPE_CL_STARTINFO) + { + // send vote options + CNetMsg_Sv_VoteClearOptions ClearMsg; + Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientId); + CVoteOption *pCurrent = m_pVoteOptionFirst; + while(pCurrent) + { + CNetMsg_Sv_VoteOption OptionMsg; + OptionMsg.m_pCommand = pCurrent->m_aCommand; + Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientId); + pCurrent = pCurrent->m_pNext; + } + + // send tuning parameters to client + SendTuningParams(ClientId); + + // + CNetMsg_Sv_ReadyToEnter m; + Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientId); + } + } + else if (MsgId == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused) + { + CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg; + + if(g_Config.m_SvSpamprotection && p->m_Last_Emote && p->m_Last_Emote+Server()->TickSpeed()*3 > Server()->Tick()) + return; + + p->m_Last_Emote = Server()->Tick(); + + SendEmoticon(ClientId, pMsg->m_Emoticon); + } + else if (MsgId == NETMSGTYPE_CL_KILL && !m_World.m_Paused) + { + if(p->m_Last_Kill && p->m_Last_Kill+Server()->TickSpeed()*3 > Server()->Tick()) + return; + + p->m_Last_Kill = Server()->Tick(); + p->KillCharacter(WEAPON_SELF); + p->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()*3; + } +} + +void CGameContext::ConTuneParam(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + const char *pParamName = pResult->GetString(0); + float NewValue = pResult->GetFloat(1); + + if(pSelf->Tuning()->Set(pParamName, NewValue)) + { + dbg_msg("tuning", "%s changed to %.2f", pParamName, NewValue); + pSelf->SendTuningParams(-1); + } + else + dbg_msg("tuning", "No such tuning parameter"); +} + +void CGameContext::ConTuneReset(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + CTuningParams p; + *pSelf->Tuning() = p; + pSelf->SendTuningParams(-1); + dbg_msg("tuning", "Tuning reset"); +} + +void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + for(int i = 0; i < pSelf->Tuning()->Num(); i++) + { + float v; + pSelf->Tuning()->Get(i, &v); + dbg_msg("tuning", "%s %.2f", pSelf->Tuning()->m_apNames[i], v); + } +} + +void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + pSelf->m_pController->ChangeMap(pResult->GetString(0)); +} + +void CGameContext::ConRestart(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + if(pResult->NumArguments()) + pSelf->m_pController->DoWarmup(pResult->GetInteger(0)); + else + pSelf->m_pController->StartRound(); +} + +void CGameContext::ConBroadcast(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + pSelf->SendBroadcast(pResult->GetString(0), -1); +} + +void CGameContext::ConSay(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + pSelf->SendChat(-1, CGameContext::CHAT_ALL, pResult->GetString(0)); +} + +void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + int ClientId = clamp(pResult->GetInteger(0), 0, (int)MAX_CLIENTS-1); + int Team = clamp(pResult->GetInteger(1), -1, 1); + + dbg_msg("", "%d %d", ClientId, Team); + + if(!pSelf->m_apPlayers[ClientId]) + return; + + pSelf->m_apPlayers[ClientId]->SetTeam(Team); + (void)pSelf->m_pController->CheckTeamBalance(); +} + +void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + int Len = str_length(pResult->GetString(0)); + + CGameContext::CVoteOption *pOption = (CGameContext::CVoteOption *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CGameContext::CVoteOption) + Len); + pOption->m_pNext = 0; + pOption->m_pPrev = pSelf->m_pVoteOptionLast; + if(pOption->m_pPrev) + pOption->m_pPrev->m_pNext = pOption; + pSelf->m_pVoteOptionLast = pOption; + if(!pSelf->m_pVoteOptionFirst) + pSelf->m_pVoteOptionFirst = pOption; + + mem_copy(pOption->m_aCommand, pResult->GetString(0), Len+1); + dbg_msg("server", "added option '%s'", pOption->m_aCommand); + + CNetMsg_Sv_VoteOption OptionMsg; + OptionMsg.m_pCommand = pOption->m_aCommand; + pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1); +} + +void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + if(str_comp_nocase(pResult->GetString(0), "yes") == 0) + pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_YES; + else if(str_comp_nocase(pResult->GetString(0), "no") == 0) + pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO; + dbg_msg("server", "forcing vote %s", pResult->GetString(0)); +} + +void CGameContext::ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + pfnCallback(pResult, pCallbackUserData); + if(pResult->NumArguments()) + { + CNetMsg_Sv_Motd Msg; + Msg.m_pMessage = g_Config.m_SvMotd; + CGameContext *pSelf = (CGameContext *)pUserData; + for(int i = 0; i < MAX_CLIENTS; ++i) + if(pSelf->m_apPlayers[i]) + pSelf->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, i); + } +} + +void CGameContext::OnConsoleInit() +{ + m_pServer = Kernel()->RequestInterface<IServer>(); + m_pConsole = Kernel()->RequestInterface<IConsole>(); + + Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, ""); + Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, ""); + Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, ""); + + Console()->Register("change_map", "r", CFGFLAG_SERVER, ConChangeMap, this, ""); + Console()->Register("restart", "?i", CFGFLAG_SERVER, ConRestart, this, ""); + Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, ""); + Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, ""); + Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConSetTeam, this, ""); + + Console()->Register("addvote", "r", CFGFLAG_SERVER, ConAddVote, this, ""); + Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, ""); + + Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this); +} + +void CGameContext::OnInit(/*class IKernel *pKernel*/) +{ + m_pServer = Kernel()->RequestInterface<IServer>(); + m_pConsole = Kernel()->RequestInterface<IConsole>(); + m_World.SetGameServer(this); + m_Events.SetGameServer(this); + + //if(!data) // only load once + //data = load_data_from_memory(internal_data); + + for(int i = 0; i < NUM_NETOBJTYPES; i++) + Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); + + m_Layers.Init(Kernel()); + m_Collision.Init(&m_Layers); + + // reset everything here + //world = new GAMEWORLD; + //players = new CPlayer[MAX_CLIENTS]; + + // select gametype + if(str_comp(g_Config.m_SvGametype, "mod") == 0) + m_pController = new CGameControllerMOD(this); + else if(str_comp(g_Config.m_SvGametype, "ctf") == 0) + m_pController = new CGameControllerCTF(this); + else if(str_comp(g_Config.m_SvGametype, "tdm") == 0) + m_pController = new CGameControllerTDM(this); + else + m_pController = new CGameControllerDM(this); + + // setup core world + //for(int i = 0; i < MAX_CLIENTS; i++) + // game.players[i].core.world = &game.world.core; + + // create all entities from the game layer + CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer(); + CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data); + + + + + /* + num_spawn_points[0] = 0; + num_spawn_points[1] = 0; + num_spawn_points[2] = 0; + */ + + for(int y = 0; y < pTileMap->m_Height; y++) + { + for(int x = 0; x < pTileMap->m_Width; x++) + { + int Index = pTiles[y*pTileMap->m_Width+x].m_Index; + + if(Index >= ENTITY_OFFSET) + { + vec2 Pos(x*32.0f+16.0f, y*32.0f+16.0f); + m_pController->OnEntity(Index-ENTITY_OFFSET, Pos); + } + } + } + + //game.world.insert_entity(game.Controller); + +#ifdef CONF_DEBUG + if(g_Config.m_DbgDummies) + { + for(int i = 0; i < g_Config.m_DbgDummies ; i++) + { + OnClientConnected(MAX_CLIENTS-i-1); + } + } +#endif +} + +void CGameContext::OnShutdown() +{ + delete m_pController; + m_pController = 0; + Clear(); } -void GAMECONTEXT::snap(int client_id) +void CGameContext::OnSnap(int ClientId) { - world.snap(client_id); - controller->snap(client_id); - events.snap(client_id); + m_World.Snap(ClientId); + m_pController->Snap(ClientId); + m_Events.Snap(ClientId); for(int i = 0; i < MAX_CLIENTS; i++) { - if(players[i]) - players[i]->snap(client_id); + if(m_apPlayers[i]) + m_apPlayers[i]->Snap(ClientId); } } +void CGameContext::OnPreSnap() {} +void CGameContext::OnPostSnap() +{ + m_Events.Clear(); +} + +const char *CGameContext::Version() { return GAME_VERSION; } +const char *CGameContext::NetVersion() { return GAME_NETVERSION; } + +IGameServer *CreateGameServer() { return new CGameContext; } diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h new file mode 100644 index 00000000..d55203e7 --- /dev/null +++ b/src/game/server/gamecontext.h @@ -0,0 +1,168 @@ +#ifndef GAME_SERVER_GAMECONTEXT_H +#define GAME_SERVER_GAMECONTEXT_H + +#include <engine/server.h> +#include <engine/console.h> +#include <engine/shared/memheap.h> + +#include <game/layers.h> + +#include "eventhandler.h" +#include "gamecontroller.h" +#include "gameworld.h" +#include "player.h" + +/* + Tick + Game Context (CGameContext::tick) + Game World (GAMEWORLD::tick) + Reset world if requested (GAMEWORLD::reset) + All entities in the world (ENTITY::tick) + All entities in the world (ENTITY::tick_defered) + Remove entities marked for deletion (GAMEWORLD::remove_entities) + Game Controller (GAMECONTROLLER::tick) + All players (CPlayer::tick) + + + Snap + Game Context (CGameContext::snap) + Game World (GAMEWORLD::snap) + All entities in the world (ENTITY::snap) + Game Controller (GAMECONTROLLER::snap) + Events handler (EVENT_HANDLER::snap) + All players (CPlayer::snap) + +*/ +class CGameContext : public IGameServer +{ + IServer *m_pServer; + class IConsole *m_pConsole; + CLayers m_Layers; + CCollision m_Collision; + CNetObjHandler m_NetObjHandler; + CTuningParams m_Tuning; + + static void ConTuneParam(IConsole::IResult *pResult, void *pUserData); + static void ConTuneReset(IConsole::IResult *pResult, void *pUserData); + static void ConTuneDump(IConsole::IResult *pResult, void *pUserData); + static void ConChangeMap(IConsole::IResult *pResult, void *pUserData); + static void ConRestart(IConsole::IResult *pResult, void *pUserData); + static void ConBroadcast(IConsole::IResult *pResult, void *pUserData); + static void ConSay(IConsole::IResult *pResult, void *pUserData); + static void ConSetTeam(IConsole::IResult *pResult, void *pUserData); + static void ConAddVote(IConsole::IResult *pResult, void *pUserData); + static void ConVote(IConsole::IResult *pResult, void *pUserData); + static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + + CGameContext(int Resetting); + void Construct(int Resetting); + + bool m_Resetting; +public: + IServer *Server() const { return m_pServer; } + class IConsole *Console() { return m_pConsole; } + CCollision *Collision() { return &m_Collision; } + CTuningParams *Tuning() { return &m_Tuning; } + + CGameContext(); + ~CGameContext(); + + void Clear(); + + CEventHandler m_Events; + CPlayer *m_apPlayers[MAX_CLIENTS]; + + IGameController *m_pController; + CGameWorld m_World; + + // helper functions + class CCharacter *GetPlayerChar(int ClientId); + + // voting + void StartVote(const char *pDesc, const char *pCommand); + void EndVote(); + void SendVoteSet(int ClientId); + void SendVoteStatus(int ClientId, int Total, int Yes, int No); + void AbortVoteKickOnDisconnect(int ClientId); + + int m_VoteCreator; + int64 m_VoteCloseTime; + bool m_VoteUpdate; + int m_VotePos; + char m_aVoteDescription[512]; + char m_aVoteCommand[512]; + int m_VoteEnforce; + enum + { + VOTE_ENFORCE_UNKNOWN=0, + VOTE_ENFORCE_NO, + VOTE_ENFORCE_YES, + }; + struct CVoteOption + { + CVoteOption *m_pNext; + CVoteOption *m_pPrev; + char m_aCommand[1]; + }; + CHeap *m_pVoteOptionHeap; + CVoteOption *m_pVoteOptionFirst; + CVoteOption *m_pVoteOptionLast; + + // helper functions + void CreateDamageInd(vec2 Pos, float AngleMod, int Amount); + void CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage); + void CreateSmoke(vec2 Pos); + void CreateHammerHit(vec2 Pos); + void CreatePlayerSpawn(vec2 Pos); + void CreateDeath(vec2 Pos, int Who); + void CreateSound(vec2 Pos, int Sound, int Mask=-1); + void CreateSoundGlobal(int Sound, int Target=-1); + + + enum + { + CHAT_ALL=-2, + CHAT_SPEC=-1, + CHAT_RED=0, + CHAT_BLUE=1 + }; + + // network + void SendChatTarget(int To, const char *pText); + void SendChat(int ClientId, int Team, const char *pText); + void SendEmoticon(int ClientId, int Emoticon); + void SendWeaponPickup(int ClientId, int Weapon); + void SendBroadcast(const char *pText, int ClientId); + + + // + void CheckPureTuning(); + void SendTuningParams(int ClientId); + + // engine events + virtual void OnInit(); + virtual void OnConsoleInit(); + virtual void OnShutdown(); + + virtual void OnTick(); + virtual void OnPreSnap(); + virtual void OnSnap(int ClientId); + virtual void OnPostSnap(); + + virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId); + + virtual void OnClientConnected(int ClientId); + virtual void OnClientEnter(int ClientId); + virtual void OnClientDrop(int ClientId); + virtual void OnClientDirectInput(int ClientId, void *pInput); + virtual void OnClientPredictedInput(int ClientId, void *pInput); + + virtual const char *Version(); + virtual const char *NetVersion(); +}; + +inline int CmaskAll() { return -1; } +inline int CmaskOne(int ClientId) { return 1<<ClientId; } +inline int CmaskAllExceptOne(int ClientId) { return 0x7fffffff^CmaskOne(ClientId); } +inline bool CmaskIsSet(int Mask, int ClientId) { return (Mask&CmaskOne(ClientId)) != 0; } +#endif diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp deleted file mode 100644 index bea087cb..00000000 --- a/src/game/server/gamecontext.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef GAME_SERVER_GAMECONTEXT_H -#define GAME_SERVER_GAMECONTEXT_H - -#include "eventhandler.hpp" -#include "gamecontroller.hpp" -#include "gameworld.hpp" -#include "player.hpp" - -/* - Tick - Game Context (GAMECONTEXT::tick) - Game World (GAMEWORLD::tick) - Reset world if requested (GAMEWORLD::reset) - All entities in the world (ENTITY::tick) - All entities in the world (ENTITY::tick_defered) - Remove entities marked for deletion (GAMEWORLD::remove_entities) - Game Controller (GAMECONTROLLER::tick) - All players (PLAYER::tick) - - - Snap - Game Context (GAMECONTEXT::snap) - Game World (GAMEWORLD::snap) - All entities in the world (ENTITY::snap) - Game Controller (GAMECONTROLLER::snap) - Events handler (EVENT_HANDLER::snap) - All players (PLAYER::snap) - -*/ -class GAMECONTEXT -{ -public: - GAMECONTEXT(); - ~GAMECONTEXT(); - - void clear(); - - EVENTHANDLER events; - PLAYER *players[MAX_CLIENTS]; - - GAMECONTROLLER *controller; - GAMEWORLD world; - - void tick(); - void snap(int client_id); - - // helper functions - class CHARACTER *get_player_char(int client_id); - - // voting - void start_vote(const char *desc, const char *command); - void end_vote(); - void send_vote_set(int cid); - void send_vote_status(int cid); - void abort_vote_kick_on_disconnect(int client_id); - int vote_creator; - int64 vote_closetime; - char vote_description[512]; - char vote_command[512]; - int vote_enforce; - enum - { - VOTE_ENFORCE_UNKNOWN=0, - VOTE_ENFORCE_NO, - VOTE_ENFORCE_YES, - }; - - // helper functions - void create_damageind(vec2 p, float angle_mod, int amount); - void create_explosion(vec2 p, int owner, int weapon, bool bnodamage); - void create_smoke(vec2 p); - void create_hammerhit(vec2 p); - void create_playerspawn(vec2 p); - void create_death(vec2 p, int who); - void create_sound(vec2 pos, int sound, int mask=-1); - void create_sound_global(int sound, int target=-1); - - - enum - { - CHAT_ALL=-2, - CHAT_SPEC=-1, - CHAT_RED=0, - CHAT_BLUE=1 - }; - - // network - void send_chat_target(int to, const char *text); - void send_chat(int cid, int team, const char *text); - void send_emoticon(int cid, int emoticon); - void send_weapon_pickup(int cid, int weapon); - void send_broadcast(const char *text, int cid); - -}; - -extern GAMECONTEXT game; - -// MISC stuff, move to a better place later on - -extern TUNING_PARAMS tuning; -inline int cmask_all() { return -1; } -inline int cmask_one(int cid) { return 1<<cid; } -inline int cmask_all_except_one(int cid) { return 0x7fffffff^cmask_one(cid); } -inline bool cmask_is_set(int mask, int cid) { return (mask&cmask_one(cid)) != 0; } -#endif diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index cdbace8e..a822f7ca 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -1,607 +1,614 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <string.h> -#include <engine/e_config.h> -#include <engine/e_server_interface.h> -#include <game/mapitems.hpp> +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include <engine/shared/config.h> +#include <game/mapitems.h> -#include <game/generated/g_protocol.hpp> +#include <game/generated/protocol.h> -#include "entities/pickup.hpp" -#include "gamecontroller.hpp" -#include "gamecontext.hpp" +#include "entities/pickup.h" +#include "gamecontroller.h" +#include "gamecontext.h" - -GAMECONTROLLER::GAMECONTROLLER() +IGameController::IGameController(class CGameContext *pGameServer) { - gametype = "unknown"; + m_pGameServer = pGameServer; + m_pServer = m_pGameServer->Server(); + m_pGameType = "unknown"; // - do_warmup(config.sv_warmup); - game_over_tick = -1; - sudden_death = 0; - round_start_tick = server_tick(); - round_count = 0; - game_flags = 0; - teamscore[0] = 0; - teamscore[1] = 0; - map_wish[0] = 0; - - unbalanced_tick = -1; - force_balanced = false; - - num_spawn_points[0] = 0; - num_spawn_points[1] = 0; - num_spawn_points[2] = 0; + DoWarmup(g_Config.m_SvWarmup); + m_GameOverTick = -1; + m_SuddenDeath = 0; + m_RoundStartTick = Server()->Tick(); + m_RoundCount = 0; + m_GameFlags = 0; + m_aTeamscore[0] = 0; + m_aTeamscore[1] = 0; + m_aMapWish[0] = 0; + + m_UnbalancedTick = -1; + m_ForceBalanced = false; + + m_aNumSpawnPoints[0] = 0; + m_aNumSpawnPoints[1] = 0; + m_aNumSpawnPoints[2] = 0; } -GAMECONTROLLER::~GAMECONTROLLER() +IGameController::~IGameController() { } -float GAMECONTROLLER::evaluate_spawn_pos(SPAWNEVAL *eval, vec2 pos) +float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) { - float score = 0.0f; - CHARACTER *c = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER); - for(; c; c = (CHARACTER *)c->typenext()) + float Score = 0.0f; + CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER)); + for(; pC; pC = (CCharacter *)pC->TypeNext()) { // team mates are not as dangerous as enemies - float scoremod = 1.0f; - if(eval->friendly_team != -1 && c->team == eval->friendly_team) - scoremod = 0.5f; + float Scoremod = 1.0f; + if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam) + Scoremod = 0.5f; - float d = distance(pos, c->pos); + float d = distance(Pos, pC->m_Pos); if(d == 0) - score += 1000000000.0f; + Score += 1000000000.0f; else - score += 1.0f/d; + Score += 1.0f/d; } - return score; + return Score; } -void GAMECONTROLLER::evaluate_spawn_type(SPAWNEVAL *eval, int t) +void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int T) { // get spawn point - for(int i = 0; i < num_spawn_points[t]; i++) + for(int i = 0; i < m_aNumSpawnPoints[T]; i++) { - vec2 p = spawn_points[t][i]; - float s = evaluate_spawn_pos(eval, p); - if(!eval->got || eval->score > s) + vec2 P = m_aaSpawnPoints[T][i]; + float S = EvaluateSpawnPos(pEval, P); + if(!pEval->m_Got || pEval->m_Score > S) { - eval->got = true; - eval->score = s; - eval->pos = p; + pEval->m_Got = true; + pEval->m_Score = S; + pEval->m_Pos = P; } } } -bool GAMECONTROLLER::can_spawn(PLAYER *player, vec2 *out_pos) +bool IGameController::CanSpawn(CPlayer *pPlayer, vec2 *pOutPos) { - SPAWNEVAL eval; + CSpawnEval Eval; // spectators can't spawn - if(player->team == -1) + if(pPlayer->GetTeam() == -1) return false; - if(is_teamplay()) + if(IsTeamplay()) { - eval.friendly_team = player->team; + Eval.m_FriendlyTeam = pPlayer->GetTeam(); // try first try own team spawn, then normal spawn and then enemy - evaluate_spawn_type(&eval, 1+(player->team&1)); - if(!eval.got) + EvaluateSpawnType(&Eval, 1+(pPlayer->GetTeam()&1)); + if(!Eval.m_Got) { - evaluate_spawn_type(&eval, 0); - if(!eval.got) - evaluate_spawn_type(&eval, 1+((player->team+1)&1)); + EvaluateSpawnType(&Eval, 0); + if(!Eval.m_Got) + EvaluateSpawnType(&Eval, 1+((pPlayer->GetTeam()+1)&1)); } } else { - evaluate_spawn_type(&eval, 0); - evaluate_spawn_type(&eval, 1); - evaluate_spawn_type(&eval, 2); + EvaluateSpawnType(&Eval, 0); + EvaluateSpawnType(&Eval, 1); + EvaluateSpawnType(&Eval, 2); } - *out_pos = eval.pos; - return eval.got; + *pOutPos = Eval.m_Pos; + return Eval.m_Got; } -bool GAMECONTROLLER::on_entity(int index, vec2 pos) +bool IGameController::OnEntity(int Index, vec2 Pos) { - int type = -1; - int subtype = 0; + int Type = -1; + int SubType = 0; - if(index == ENTITY_SPAWN) - spawn_points[0][num_spawn_points[0]++] = pos; - else if(index == ENTITY_SPAWN_RED) - spawn_points[1][num_spawn_points[1]++] = pos; - else if(index == ENTITY_SPAWN_BLUE) - spawn_points[2][num_spawn_points[2]++] = pos; - else if(index == ENTITY_ARMOR_1) - type = POWERUP_ARMOR; - else if(index == ENTITY_HEALTH_1) - type = POWERUP_HEALTH; - else if(index == ENTITY_WEAPON_SHOTGUN) + if(Index == ENTITY_SPAWN) + m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos; + else if(Index == ENTITY_SPAWN_RED) + m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos; + else if(Index == ENTITY_SPAWN_BLUE) + m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = Pos; + else if(Index == ENTITY_ARMOR_1) + Type = POWERUP_ARMOR; + else if(Index == ENTITY_HEALTH_1) + Type = POWERUP_HEALTH; + else if(Index == ENTITY_WEAPON_SHOTGUN) { - type = POWERUP_WEAPON; - subtype = WEAPON_SHOTGUN; + Type = POWERUP_WEAPON; + SubType = WEAPON_SHOTGUN; } - else if(index == ENTITY_WEAPON_GRENADE) + else if(Index == ENTITY_WEAPON_GRENADE) { - type = POWERUP_WEAPON; - subtype = WEAPON_GRENADE; + Type = POWERUP_WEAPON; + SubType = WEAPON_GRENADE; } - else if(index == ENTITY_WEAPON_RIFLE) + else if(Index == ENTITY_WEAPON_RIFLE) { - type = POWERUP_WEAPON; - subtype = WEAPON_RIFLE; + Type = POWERUP_WEAPON; + SubType = WEAPON_RIFLE; } - else if(index == ENTITY_POWERUP_NINJA && config.sv_powerups) + else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups) { - type = POWERUP_NINJA; - subtype = WEAPON_NINJA; + Type = POWERUP_NINJA; + SubType = WEAPON_NINJA; } - if(type != -1) + if(Type != -1) { - PICKUP *pickup = new PICKUP(type, subtype); - pickup->pos = pos; + CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType); + pPickup->m_Pos = Pos; return true; } return false; } -void GAMECONTROLLER::endround() +void IGameController::EndRound() { - if(warmup) // game can't end when we are running warmup + if(m_Warmup) // game can't end when we are running warmup return; - game.world.paused = true; - game_over_tick = server_tick(); - sudden_death = 0; + GameServer()->m_World.m_Paused = true; + m_GameOverTick = Server()->Tick(); + m_SuddenDeath = 0; } -void GAMECONTROLLER::resetgame() +void IGameController::ResetGame() { - game.world.reset_requested = true; + GameServer()->m_World.m_ResetRequested = true; } -const char *GAMECONTROLLER::get_team_name(int team) +const char *IGameController::GetTeamName(int Team) { - if(is_teamplay()) + if(IsTeamplay()) { - if(team == 0) + if(Team == 0) return "red team"; - else if(team == 1) + else if(Team == 1) return "blue team"; } else { - if(team == 0) + if(Team == 0) return "game"; } return "spectators"; } -static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; } +static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; } -void GAMECONTROLLER::startround() +void IGameController::StartRound() { - resetgame(); - - round_start_tick = server_tick(); - sudden_death = 0; - game_over_tick = -1; - game.world.paused = false; - teamscore[0] = 0; - teamscore[1] = 0; - unbalanced_tick = -1; - force_balanced = false; - dbg_msg("game","start round type='%s' teamplay='%d'", gametype, game_flags&GAMEFLAG_TEAMS); + ResetGame(); + + m_RoundStartTick = Server()->Tick(); + m_SuddenDeath = 0; + m_GameOverTick = -1; + GameServer()->m_World.m_Paused = false; + m_aTeamscore[0] = 0; + m_aTeamscore[1] = 0; + m_ForceBalanced = false; + dbg_msg("game","start round type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS); } -void GAMECONTROLLER::change_map(const char *to_map) +void IGameController::ChangeMap(const char *pToMap) { - str_copy(map_wish, to_map, sizeof(map_wish)); - endround(); + str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish)); + EndRound(); } -void GAMECONTROLLER::cyclemap() +void IGameController::CycleMap() { - if(map_wish[0] != 0) + if(m_aMapWish[0] != 0) { - dbg_msg("game", "rotating map to %s", map_wish); - str_copy(config.sv_map, map_wish, sizeof(config.sv_map)); - map_wish[0] = 0; - round_count = 0; + dbg_msg("game", "rotating map to %s", m_aMapWish); + str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap)); + m_aMapWish[0] = 0; + m_RoundCount = 0; return; } - if(!strlen(config.sv_maprotation)) + if(!str_length(g_Config.m_SvMaprotation)) return; - if(round_count < config.sv_rounds_per_map-1) + if(m_RoundCount < g_Config.m_SvRoundsPerMap-1) return; // handle maprotation - const char *map_rotation = config.sv_maprotation; - const char *current_map = config.sv_map; + const char *pMapRotation = g_Config.m_SvMaprotation; + const char *pCurrentMap = g_Config.m_SvMap; - int current_map_len = strlen(current_map); - const char *next_map = map_rotation; - while(*next_map) + int CurrentMapLen = str_length(pCurrentMap); + const char *pNextMap = pMapRotation; + while(*pNextMap) { - int wordlen = 0; - while(next_map[wordlen] && !is_separator(next_map[wordlen])) - wordlen++; + int WordLen = 0; + while(pNextMap[WordLen] && !IsSeparator(pNextMap[WordLen])) + WordLen++; - if(wordlen == current_map_len && strncmp(next_map, current_map, current_map_len) == 0) + if(WordLen == CurrentMapLen && str_comp_num(pNextMap, pCurrentMap, CurrentMapLen) == 0) { // map found - next_map += current_map_len; - while(*next_map && is_separator(*next_map)) - next_map++; + pNextMap += CurrentMapLen; + while(*pNextMap && IsSeparator(*pNextMap)) + pNextMap++; break; } - next_map++; + pNextMap++; } // restart rotation - if(next_map[0] == 0) - next_map = map_rotation; + if(pNextMap[0] == 0) + pNextMap = pMapRotation; // cut out the next map - char buf[512]; + char Buf[512]; for(int i = 0; i < 512; i++) { - buf[i] = next_map[i]; - if(is_separator(next_map[i]) || next_map[i] == 0) + Buf[i] = pNextMap[i]; + if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0) { - buf[i] = 0; + Buf[i] = 0; break; } } // skip spaces int i = 0; - while(is_separator(buf[i])) + while(IsSeparator(Buf[i])) i++; - round_count = 0; + m_RoundCount = 0; - dbg_msg("game", "rotating map to %s", &buf[i]); - str_copy(config.sv_map, &buf[i], sizeof(config.sv_map)); + dbg_msg("game", "rotating map to %s", &Buf[i]); + str_copy(g_Config.m_SvMap, &Buf[i], sizeof(g_Config.m_SvMap)); } -void GAMECONTROLLER::post_reset() +void IGameController::PostReset() { for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i]) + if(GameServer()->m_apPlayers[i]) { - game.players[i]->respawn(); - game.players[i]->score = 0; + GameServer()->m_apPlayers[i]->Respawn(); + GameServer()->m_apPlayers[i]->m_Score = 0; } } } -void GAMECONTROLLER::on_player_info_change(class PLAYER *p) +void IGameController::OnPlayerInfoChange(class CPlayer *pP) { - const int team_colors[2] = {65387, 10223467}; - if(is_teamplay()) + const int aTeamColors[2] = {65387, 10223467}; + if(IsTeamplay()) { - if(p->team >= 0 || p->team <= 1) + if(pP->GetTeam() >= 0 || pP->GetTeam() <= 1) { - p->use_custom_color = 1; - p->color_body = team_colors[p->team]; - p->color_feet = team_colors[p->team]; + pP->m_TeeInfos.m_UseCustomColor = 1; + pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()]; + pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()]; } } } -int GAMECONTROLLER::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon) +int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon) { // do scoreing - if(!killer) + if(!pKiller) return 0; - if(killer == victim->player) - victim->player->score--; // suicide + if(pKiller == pVictim->GetPlayer()) + pVictim->GetPlayer()->m_Score--; // suicide else { - if(is_teamplay() && victim->team == killer->team) - killer->score--; // teamkill + if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam()) + pKiller->m_Score--; // teamkill else - killer->score++; // normal kill + pKiller->m_Score++; // normal kill } return 0; } -void GAMECONTROLLER::on_character_spawn(class CHARACTER *chr) +void IGameController::OnCharacterSpawn(class CCharacter *pChr) { // default health - chr->health = 10; + pChr->IncreaseHealth(10); // give default weapons - chr->weapons[WEAPON_HAMMER].got = 1; - chr->weapons[WEAPON_HAMMER].ammo = -1; - chr->weapons[WEAPON_GUN].got = 1; - chr->weapons[WEAPON_GUN].ammo = 10; + pChr->GiveWeapon(WEAPON_HAMMER, -1); + pChr->GiveWeapon(WEAPON_GUN, 10); } -void GAMECONTROLLER::do_warmup(int seconds) +void IGameController::DoWarmup(int Seconds) { - warmup = seconds*server_tickspeed(); + if(Seconds < 0) + m_Warmup = 0; + else + m_Warmup = Seconds*Server()->TickSpeed(); } -bool GAMECONTROLLER::is_friendly_fire(int cid1, int cid2) +bool IGameController::IsFriendlyFire(int Cid1, int Cid2) { - if(cid1 == cid2) + if(Cid1 == Cid2) return false; - if(is_teamplay()) + if(IsTeamplay()) { - if(!game.players[cid1] || !game.players[cid2]) + if(!GameServer()->m_apPlayers[Cid1] || !GameServer()->m_apPlayers[Cid2]) return false; - if(game.players[cid1]->team == game.players[cid2]->team) + if(GameServer()->m_apPlayers[Cid1]->GetTeam() == GameServer()->m_apPlayers[Cid2]->GetTeam()) return true; } return false; } -bool GAMECONTROLLER::is_force_balanced() +bool IGameController::IsForceBalanced() { - if(force_balanced) + if(m_ForceBalanced) { - force_balanced = false; + m_ForceBalanced = false; return true; } else return false; } -void GAMECONTROLLER::tick() +bool IGameController::CanBeMovedOnBalance(int Cid) +{ + return true; +} + +void IGameController::Tick() { // do warmup - if(warmup) + if(m_Warmup) { - warmup--; - if(!warmup) - startround(); + m_Warmup--; + if(!m_Warmup) + StartRound(); } - if(game_over_tick != -1) + if(m_GameOverTick != -1) { // game over.. wait for restart - if(server_tick() > game_over_tick+server_tickspeed()*10) + if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10) { - cyclemap(); - startround(); - round_count++; + CycleMap(); + StartRound(); + m_RoundCount++; } } // do team-balancing - if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60) + if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) { dbg_msg("game", "Balancing teams"); - int t[2] = {0,0}; - int tscore[2] = {0,0}; + int aT[2] = {0,0}; + int aTScore[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i] && game.players[i]->team != -1) + if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != -1) { - t[game.players[i]->team]++; - tscore[game.players[i]->team]+=game.players[i]->score; + aT[GameServer()->m_apPlayers[i]->GetTeam()]++; + aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += GameServer()->m_apPlayers[i]->m_Score; } } // are teams unbalanced? - if(abs(t[0]-t[1]) >= 2) + if(absolute(aT[0]-aT[1]) >= 2) { - int m = (t[0] > t[1]) ? 0 : 1; - int num_balance = abs(t[0]-t[1]) / 2; + int M = (aT[0] > aT[1]) ? 0 : 1; + int NumBalance = absolute(aT[0]-aT[1]) / 2; do { - PLAYER *p = 0; - int pd = tscore[m]; + CPlayer *pP = 0; + int PD = aTScore[M]; for(int i = 0; i < MAX_CLIENTS; i++) { - if(!game.players[i]) + if(!GameServer()->m_apPlayers[i]) + continue; + if(!CanBeMovedOnBalance(i)) continue; - // remember the player who would cause lowest score-difference - if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd)) + if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+GameServer()->m_apPlayers[i]->m_Score) - (aTScore[M]-GameServer()->m_apPlayers[i]->m_Score)) < PD)) { - p = game.players[i]; - pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score)); + pP = GameServer()->m_apPlayers[i]; + PD = absolute((aTScore[M^1]+pP->m_Score) - (aTScore[M]-pP->m_Score)); } } // move the player to other team without losing his score // TODO: change in player::set_team needed: player won't lose score on team-change - int score_before = p->score; - p->set_team(m^1); - p->score = score_before; + int ScoreBefore = pP->m_Score; + pP->SetTeam(M^1); + pP->m_Score = ScoreBefore; - p->respawn(); - p->force_balanced = true; - } while (--num_balance); + pP->Respawn(); + pP->m_ForceBalanced = true; + } while (--NumBalance); - force_balanced = true; + m_ForceBalanced = true; } - unbalanced_tick = -1; + m_UnbalancedTick = -1; } // update browse info - int prog = -1; - if(config.sv_timelimit > 0) - prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60)); + int Prog = -1; + if(g_Config.m_SvTimelimit > 0) + Prog = max(Prog, (Server()->Tick()-m_RoundStartTick) * 100 / (g_Config.m_SvTimelimit*Server()->TickSpeed()*60)); - if(config.sv_scorelimit) + if(g_Config.m_SvScorelimit) { - if(is_teamplay()) + if(IsTeamplay()) { - prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit); - prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit); + Prog = max(Prog, (m_aTeamscore[0]*100)/g_Config.m_SvScorelimit); + Prog = max(Prog, (m_aTeamscore[1]*100)/g_Config.m_SvScorelimit); } else { for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i]) - prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit); + if(GameServer()->m_apPlayers[i]) + Prog = max(Prog, (GameServer()->m_apPlayers[i]->m_Score*100)/g_Config.m_SvScorelimit); } } } - if(warmup) - prog = -1; + if(m_Warmup) + Prog = -1; - server_setbrowseinfo(gametype, prog); + Server()->SetBrowseInfo(m_pGameType, Prog); } -bool GAMECONTROLLER::is_teamplay() const +bool IGameController::IsTeamplay() const { - return game_flags&GAMEFLAG_TEAMS; + return m_GameFlags&GAMEFLAG_TEAMS; } -void GAMECONTROLLER::snap(int snapping_client) +void IGameController::Snap(int SnappingClient) { - NETOBJ_GAME *gameobj = (NETOBJ_GAME *)snap_new_item(NETOBJTYPE_GAME, 0, sizeof(NETOBJ_GAME)); - gameobj->paused = game.world.paused; - gameobj->game_over = game_over_tick==-1?0:1; - gameobj->sudden_death = sudden_death; + CNetObj_Game *pGameObj = (CNetObj_Game *)Server()->SnapNewItem(NETOBJTYPE_GAME, 0, sizeof(CNetObj_Game)); + pGameObj->m_Paused = GameServer()->m_World.m_Paused; + pGameObj->m_GameOver = m_GameOverTick==-1?0:1; + pGameObj->m_SuddenDeath = m_SuddenDeath; - gameobj->score_limit = config.sv_scorelimit; - gameobj->time_limit = config.sv_timelimit; - gameobj->round_start_tick = round_start_tick; - gameobj->flags = game_flags; + pGameObj->m_ScoreLimit = g_Config.m_SvScorelimit; + pGameObj->m_TimeLimit = g_Config.m_SvTimelimit; + pGameObj->m_RoundStartTick = m_RoundStartTick; + pGameObj->m_Flags = m_GameFlags; - gameobj->warmup = warmup; + pGameObj->m_Warmup = m_Warmup; - gameobj->round_num = (strlen(config.sv_maprotation) && config.sv_rounds_per_map) ? config.sv_rounds_per_map : 0; - gameobj->round_current = round_count+1; + pGameObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0; + pGameObj->m_RoundCurrent = m_RoundCount+1; - if(snapping_client == -1) + if(SnappingClient == -1) { // we are recording a demo, just set the scores - gameobj->teamscore_red = teamscore[0]; - gameobj->teamscore_blue = teamscore[1]; + pGameObj->m_TeamscoreRed = m_aTeamscore[0]; + pGameObj->m_TeamscoreBlue = m_aTeamscore[1]; } else { // TODO: this little hack should be removed - gameobj->teamscore_red = is_teamplay() ? teamscore[0] : game.players[snapping_client]->score; - gameobj->teamscore_blue = teamscore[1]; + pGameObj->m_TeamscoreRed = IsTeamplay() ? m_aTeamscore[0] : GameServer()->m_apPlayers[SnappingClient]->m_Score; + pGameObj->m_TeamscoreBlue = m_aTeamscore[1]; } } -int GAMECONTROLLER::get_auto_team(int notthisid) +int IGameController::GetAutoTeam(int Notthisid) { // this will force the auto balancer to work overtime aswell - if(config.dbg_stress) + if(g_Config.m_DbgStress) return 0; - int numplayers[2] = {0,0}; + int aNumplayers[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i] && i != notthisid) + if(GameServer()->m_apPlayers[i] && i != Notthisid) { - if(game.players[i]->team == 0 || game.players[i]->team == 1) - numplayers[game.players[i]->team]++; + if(GameServer()->m_apPlayers[i]->GetTeam() == 0 || GameServer()->m_apPlayers[i]->GetTeam() == 1) + aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++; } } - int team = 0; - if(is_teamplay()) - team = numplayers[0] > numplayers[1] ? 1 : 0; + int Team = 0; + if(IsTeamplay()) + Team = aNumplayers[0] > aNumplayers[1] ? 1 : 0; - if(can_join_team(team, notthisid)) - return team; + if(CanJoinTeam(Team, Notthisid)) + return Team; return -1; } -bool GAMECONTROLLER::can_join_team(int team, int notthisid) +bool IGameController::CanJoinTeam(int Team, int Notthisid) { - (void)team; - int numplayers[2] = {0,0}; + if(Team == -1) + return true; + + int aNumplayers[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i] && i != notthisid) + if(GameServer()->m_apPlayers[i] && i != Notthisid) { - if(game.players[i]->team >= 0 || game.players[i]->team == 1) - numplayers[game.players[i]->team]++; + if(GameServer()->m_apPlayers[i]->GetTeam() >= 0 || GameServer()->m_apPlayers[i]->GetTeam() == 1) + aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++; } } - return (numplayers[0] + numplayers[1]) < config.sv_max_clients-config.sv_spectator_slots; + return (aNumplayers[0] + aNumplayers[1]) < g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots; } -bool GAMECONTROLLER::check_team_balance() +bool IGameController::CheckTeamBalance() { - if(!is_teamplay() || !config.sv_teambalance_time) + if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) return true; - int t[2] = {0, 0}; + int aT[2] = {0, 0}; for(int i = 0; i < MAX_CLIENTS; i++) { - PLAYER *p = game.players[i]; - if(p && p->team != -1) - t[p->team]++; + CPlayer *pP = GameServer()->m_apPlayers[i]; + if(pP && pP->GetTeam() != -1) + aT[pP->GetTeam()]++; } - if(abs(t[0]-t[1]) >= 2) + if(absolute(aT[0]-aT[1]) >= 2) { - dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", t[0], t[1]); - if (game.controller->unbalanced_tick == -1) - game.controller->unbalanced_tick = server_tick(); + dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", aT[0], aT[1]); + if(GameServer()->m_pController->m_UnbalancedTick == -1) + GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); return false; } else { - dbg_msg("game", "Team is balanced (red=%d blue=%d)", t[0], t[1]); - game.controller->unbalanced_tick = -1; + dbg_msg("game", "Team is balanced (red=%d blue=%d)", aT[0], aT[1]); + GameServer()->m_pController->m_UnbalancedTick = -1; return true; } } -bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam) +bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) { - int t[2] = {0, 0}; + int aT[2] = {0, 0}; - if (!is_teamplay() || jointeam == -1 || !config.sv_teambalance_time) + if (!IsTeamplay() || JoinTeam == -1 || !g_Config.m_SvTeambalanceTime) return true; for(int i = 0; i < MAX_CLIENTS; i++) { - PLAYER *p = game.players[i]; - if(p && p->team != -1) - t[p->team]++; + CPlayer *pP = GameServer()->m_apPlayers[i]; + if(pP && pP->GetTeam() != -1) + aT[pP->GetTeam()]++; } // simulate what would happen if changed team - t[jointeam]++; - if (pplayer->team != -1) - t[jointeam^1]--; + aT[JoinTeam]++; + if (pPlayer->GetTeam() != -1) + aT[JoinTeam^1]--; // there is a player-difference of at least 2 - if(abs(t[0]-t[1]) >= 2) + if(absolute(aT[0]-aT[1]) >= 2) { // player wants to join team with less players - if ((t[0] < t[1] && jointeam == 0) || (t[0] > t[1] && jointeam == 1)) + if ((aT[0] < aT[1] && JoinTeam == 0) || (aT[0] > aT[1] && JoinTeam == 1)) return true; else return false; @@ -610,62 +617,60 @@ bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam) return true; } -void GAMECONTROLLER::do_player_score_wincheck() +void IGameController::DoPlayerScoreWincheck() { - if(game_over_tick == -1 && !warmup) + if(m_GameOverTick == -1 && !m_Warmup) { // gather some stats - int topscore = 0; - int topscore_count = 0; + int Topscore = 0; + int TopscoreCount = 0; for(int i = 0; i < MAX_CLIENTS; i++) { - if(game.players[i]) + if(GameServer()->m_apPlayers[i]) { - if(game.players[i]->score > topscore) + if(GameServer()->m_apPlayers[i]->m_Score > Topscore) { - topscore = game.players[i]->score; - topscore_count = 1; + Topscore = GameServer()->m_apPlayers[i]->m_Score; + TopscoreCount = 1; } - else if(game.players[i]->score == topscore) - topscore_count++; + else if(GameServer()->m_apPlayers[i]->m_Score == Topscore) + TopscoreCount++; } } // check score win condition - if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) || - (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) + if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) || + (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { - if(topscore_count == 1) - endround(); + if(TopscoreCount == 1) + EndRound(); else - sudden_death = 1; + m_SuddenDeath = 1; } } } -void GAMECONTROLLER::do_team_score_wincheck() +void IGameController::DoTeamScoreWincheck() { - if(game_over_tick == -1 && !warmup) + if(m_GameOverTick == -1 && !m_Warmup) { // check score win condition - if((config.sv_scorelimit > 0 && (teamscore[0] >= config.sv_scorelimit || teamscore[1] >= config.sv_scorelimit)) || - (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) + if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[0] >= g_Config.m_SvScorelimit || m_aTeamscore[1] >= g_Config.m_SvScorelimit)) || + (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) { - if(teamscore[0] != teamscore[1]) - endround(); + if(m_aTeamscore[0] != m_aTeamscore[1]) + EndRound(); else - sudden_death = 1; + m_SuddenDeath = 1; } } } -int GAMECONTROLLER::clampteam(int team) +int IGameController::ClampTeam(int Team) { - if(team < 0) // spectator + if(Team < 0) // spectator return -1; - if(is_teamplay()) - return team&1; + if(IsTeamplay()) + return Team&1; return 0; } - -GAMECONTROLLER *gamecontroller = 0; diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h new file mode 100644 index 00000000..0624dcab --- /dev/null +++ b/src/game/server/gamecontroller.h @@ -0,0 +1,145 @@ +#ifndef GAME_SERVER_GAMECONTROLLER_H +#define GAME_SERVER_GAMECONTROLLER_H + +#include <base/vmath.h> + +/* + Class: Game Controller + Controls the main game logic. Keeping track of team and player score, + winning conditions and specific game logic. +*/ +class IGameController +{ + vec2 m_aaSpawnPoints[3][64]; + int m_aNumSpawnPoints[3]; + + class CGameContext *m_pGameServer; + class IServer *m_pServer; + +protected: + CGameContext *GameServer() const { return m_pGameServer; } + IServer *Server() const { return m_pServer; } + + struct CSpawnEval + { + CSpawnEval() + { + m_Got = false; + m_FriendlyTeam = -1; + m_Pos = vec2(100,100); + } + + vec2 m_Pos; + bool m_Got; + int m_FriendlyTeam; + float m_Score; + }; + + float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos); + void EvaluateSpawnType(CSpawnEval *pEval, int Type); + bool EvaluateSpawn(class CPlayer *pP, vec2 *pPos); + + void CycleMap(); + void ResetGame(); + + char m_aMapWish[128]; + + + int m_RoundStartTick; + int m_GameOverTick; + int m_SuddenDeath; + + int m_aTeamscore[2]; + + int m_Warmup; + int m_RoundCount; + + int m_GameFlags; + int m_UnbalancedTick; + bool m_ForceBalanced; + +public: + const char *m_pGameType; + + bool IsTeamplay() const; + + IGameController(class CGameContext *pGameServer); + virtual ~IGameController(); + + void DoTeamScoreWincheck(); + void DoPlayerScoreWincheck(); + + void DoWarmup(int Seconds); + + void StartRound(); + void EndRound(); + void ChangeMap(const char *pToMap); + + bool IsFriendlyFire(int Cid1, int Cid2); + + bool IsForceBalanced(); + + /* + + */ + virtual bool CanBeMovedOnBalance(int Cid); + + virtual void Tick(); + + virtual void Snap(int SnappingClient); + + /* + Function: on_entity + Called when the map is loaded to process an entity + in the map. + + Arguments: + index - Entity index. + pos - Where the entity is located in the world. + + Returns: + bool? + */ + virtual bool OnEntity(int Index, vec2 Pos); + + /* + Function: on_CCharacter_spawn + Called when a CCharacter spawns into the game world. + + Arguments: + chr - The CCharacter that was spawned. + */ + virtual void OnCharacterSpawn(class CCharacter *pChr); + + /* + Function: on_CCharacter_death + Called when a CCharacter in the world dies. + + Arguments: + victim - The CCharacter that died. + killer - The player that killed it. + weapon - What weapon that killed it. Can be -1 for undefined + weapon when switching team or player suicides. + */ + virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); + + + virtual void OnPlayerInfoChange(class CPlayer *pP); + + // + virtual bool CanSpawn(class CPlayer *pP, vec2 *pPos); + + /* + + */ + virtual const char *GetTeamName(int Team); + virtual int GetAutoTeam(int NotThisId); + virtual bool CanJoinTeam(int Team, int NotThisId); + bool CheckTeamBalance(); + bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam); + int ClampTeam(int Team); + + virtual void PostReset(); +}; + +#endif diff --git a/src/game/server/gamecontroller.hpp b/src/game/server/gamecontroller.hpp deleted file mode 100644 index 26b8a81f..00000000 --- a/src/game/server/gamecontroller.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef GAME_SERVER_GAMECONTROLLER_H -#define GAME_SERVER_GAMECONTROLLER_H - -#include <base/vmath.hpp> - -/* - Class: Game Controller - Controls the main game logic. Keeping track of team and player score, - winning conditions and specific game logic. -*/ -class GAMECONTROLLER -{ - vec2 spawn_points[3][64]; - int num_spawn_points[3]; -protected: - struct SPAWNEVAL - { - SPAWNEVAL() - { - got = false; - friendly_team = -1; - pos = vec2(100,100); - } - - vec2 pos; - bool got; - int friendly_team; - float score; - }; - - float evaluate_spawn_pos(SPAWNEVAL *eval, vec2 pos); - void evaluate_spawn_type(SPAWNEVAL *eval, int type); - bool evaluate_spawn(class PLAYER *p, vec2 *pos); - - void cyclemap(); - void resetgame(); - - char map_wish[128]; - - - int round_start_tick; - int game_over_tick; - int sudden_death; - - int teamscore[2]; - - int warmup; - int round_count; - - int game_flags; - int unbalanced_tick; - bool force_balanced; - -public: - const char *gametype; - - bool is_teamplay() const; - - GAMECONTROLLER(); - virtual ~GAMECONTROLLER(); - - void do_team_score_wincheck(); - void do_player_score_wincheck(); - - void do_warmup(int seconds); - - void startround(); - void endround(); - void change_map(const char *to_map); - - bool is_friendly_fire(int cid1, int cid2); - - bool is_force_balanced(); - - /* - - */ - virtual void tick(); - - virtual void snap(int snapping_client); - - /* - Function: on_entity - Called when the map is loaded to process an entity - in the map. - - Arguments: - index - Entity index. - pos - Where the entity is located in the world. - - Returns: - bool? - */ - virtual bool on_entity(int index, vec2 pos); - - /* - Function: on_character_spawn - Called when a character spawns into the game world. - - Arguments: - chr - The character that was spawned. - */ - virtual void on_character_spawn(class CHARACTER *chr); - - /* - Function: on_character_death - Called when a character in the world dies. - - Arguments: - victim - The character that died. - killer - The player that killed it. - weapon - What weapon that killed it. Can be -1 for undefined - weapon when switching team or player suicides. - */ - virtual int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon); - - - virtual void on_player_info_change(class PLAYER *p); - - // - virtual bool can_spawn(class PLAYER *p, vec2 *pos); - - /* - - */ - virtual const char *get_team_name(int team); - virtual int get_auto_team(int notthisid); - virtual bool can_join_team(int team, int notthisid); - bool check_team_balance(); - bool can_change_team(PLAYER *pplayer, int jointeam); - int clampteam(int team); - - virtual void post_reset(); -}; - -#endif diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp index b2146b51..3da88342 100644 --- a/src/game/server/gamemodes/ctf.cpp +++ b/src/game/server/gamemodes/ctf.cpp @@ -1,188 +1,205 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <engine/e_server_interface.h> -#include <game/mapitems.hpp> -#include <game/server/entities/character.hpp> -#include <game/server/player.hpp> -#include <game/server/gamecontext.hpp> -#include "ctf.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include <game/mapitems.h> +#include <game/server/entities/character.h> +#include <game/server/player.h> +#include <game/server/gamecontext.h> +#include "ctf.h" -GAMECONTROLLER_CTF::GAMECONTROLLER_CTF() +CGameControllerCTF::CGameControllerCTF(class CGameContext *pGameServer) +: IGameController(pGameServer) { - flags[0] = 0; - flags[1] = 0; - gametype = "CTF"; - game_flags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS; + m_apFlags[0] = 0; + m_apFlags[1] = 0; + m_pGameType = "CTF"; + m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS; } -bool GAMECONTROLLER_CTF::on_entity(int index, vec2 pos) +bool CGameControllerCTF::OnEntity(int Index, vec2 Pos) { - if(GAMECONTROLLER::on_entity(index, pos)) + if(IGameController::OnEntity(Index, Pos)) return true; - int team = -1; - if(index == ENTITY_FLAGSTAND_RED) team = 0; - if(index == ENTITY_FLAGSTAND_BLUE) team = 1; - if(team == -1) + int Team = -1; + if(Index == ENTITY_FLAGSTAND_RED) Team = 0; + if(Index == ENTITY_FLAGSTAND_BLUE) Team = 1; + if(Team == -1) return false; - FLAG *f = new FLAG(team); - f->stand_pos = pos; - f->pos = pos; - flags[team] = f; + CFlag *F = new CFlag(&GameServer()->m_World, Team); + F->m_StandPos = Pos; + F->m_Pos = Pos; + m_apFlags[Team] = F; + GameServer()->m_World.InsertEntity(F); return true; } -int GAMECONTROLLER_CTF::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weaponid) +int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID) { - GAMECONTROLLER::on_character_death(victim, killer, weaponid); - int had_flag = 0; + IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID); + int HadFlag = 0; // drop flags - for(int fi = 0; fi < 2; fi++) + for(int i = 0; i < 2; i++) { - FLAG *f = flags[fi]; - if(f && killer && f->carrying_character == killer->get_character()) - had_flag |= 2; - if(f && f->carrying_character == victim) + CFlag *F = m_apFlags[i]; + if(F && pKiller && pKiller->GetCharacter() && F->m_pCarryingCCharacter == pKiller->GetCharacter()) + HadFlag |= 2; + if(F && F->m_pCarryingCCharacter == pVictim) { - game.create_sound_global(SOUND_CTF_DROP); - f->drop_tick = server_tick(); - f->carrying_character = 0; - f->vel = vec2(0,0); + GameServer()->CreateSoundGlobal(SOUND_CTF_DROP); + F->m_DropTick = Server()->Tick(); + F->m_pCarryingCCharacter = 0; + F->m_Vel = vec2(0,0); - if(killer && killer->team != victim->team) - killer->score++; + if(pKiller && pKiller->GetTeam() != pVictim->GetPlayer()->GetTeam()) + pKiller->m_Score++; - had_flag |= 1; + HadFlag |= 1; } } - return had_flag; + return HadFlag; +} + +bool CGameControllerCTF::CanBeMovedOnBalance(int Cid) +{ + CCharacter* Character = GameServer()->m_apPlayers[Cid]->GetCharacter(); + if(Character) + { + for(int fi = 0; fi < 2; fi++) + { + CFlag *F = m_apFlags[fi]; + if(F->m_pCarryingCCharacter == Character) + return false; + } + } + return true; } -void GAMECONTROLLER_CTF::tick() +void CGameControllerCTF::Tick() { - GAMECONTROLLER::tick(); + IGameController::Tick(); - do_team_score_wincheck(); + DoTeamScoreWincheck(); for(int fi = 0; fi < 2; fi++) { - FLAG *f = flags[fi]; + CFlag *F = m_apFlags[fi]; - if(!f) + if(!F) continue; // flag hits death-tile, reset it - if(col_get((int)f->pos.x, (int)f->pos.y)&COLFLAG_DEATH) + if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH) { - game.create_sound_global(SOUND_CTF_RETURN); - f->reset(); + GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); + F->Reset(); continue; } // - if(f->carrying_character) + if(F->m_pCarryingCCharacter) { // update flag position - f->pos = f->carrying_character->pos; + F->m_Pos = F->m_pCarryingCCharacter->m_Pos; - if(flags[fi^1] && flags[fi^1]->at_stand) + if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand) { - if(distance(f->pos, flags[fi^1]->pos) < 32) + if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < 32) { // CAPTURE! \o/ - teamscore[fi^1] += 100; - f->carrying_character->player->score += 5; + m_aTeamscore[fi^1] += 100; + F->m_pCarryingCCharacter->GetPlayer()->m_Score += 5; dbg_msg("game", "flag_capture player='%d:%s'", - f->carrying_character->player->client_id, - server_clientname(f->carrying_character->player->client_id)); + F->m_pCarryingCCharacter->GetPlayer()->GetCID(), + Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID())); - char buf[512]; - float capture_time = (server_tick() - f->grab_tick)/(float)server_tickspeed(); - if(capture_time <= 60) + char Buf[512]; + float CaptureTime = (Server()->Tick() - F->m_GrabTick)/(float)Server()->TickSpeed(); + if(CaptureTime <= 60) { - str_format(buf, sizeof(buf), "the %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id), (int)capture_time%60, ((int)(capture_time*100)%100)<10?"0":"", (int)(capture_time*100)%100); + str_format(Buf, sizeof(Buf), "The %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID()), (int)CaptureTime%60, ((int)(CaptureTime*100)%100)<10?"0":"", (int)(CaptureTime*100)%100); } else { - str_format(buf, sizeof(buf), "the %s flag was captured by %s", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id)); + str_format(Buf, sizeof(Buf), "The %s flag was captured by %s", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID())); } - game.send_chat(-1, -2, buf); + GameServer()->SendChat(-1, -2, Buf); for(int i = 0; i < 2; i++) - flags[i]->reset(); + m_apFlags[i]->Reset(); - game.create_sound_global(SOUND_CTF_CAPTURE); + GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE); } - } + } } else { - CHARACTER *close_characters[MAX_CLIENTS]; - int num = game.world.find_entities(f->pos, 32.0f, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); - for(int i = 0; i < num; i++) + CCharacter *apCloseCCharacters[MAX_CLIENTS]; + int Num = GameServer()->m_World.FindEntities(F->m_Pos, 32.0f, (CEntity**)apCloseCCharacters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); + for(int i = 0; i < Num; i++) { - if(!close_characters[i]->alive || close_characters[i]->player->team == -1 || col_intersect_line(f->pos, close_characters[i]->pos, NULL, NULL)) + if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == -1 || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL)) continue; - if(close_characters[i]->team == f->team) + if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team) { // return the flag - if(!f->at_stand) + if(!F->m_AtStand) { - CHARACTER *chr = close_characters[i]; - chr->player->score += 1; + CCharacter *pChr = apCloseCCharacters[i]; + pChr->GetPlayer()->m_Score += 1; dbg_msg("game", "flag_return player='%d:%s'", - chr->player->client_id, - server_clientname(chr->player->client_id)); + pChr->GetPlayer()->GetCID(), + Server()->ClientName(pChr->GetPlayer()->GetCID())); - game.create_sound_global(SOUND_CTF_RETURN); - f->reset(); + GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); + F->Reset(); } } else { // take the flag - if(f->at_stand) + if(F->m_AtStand) { - teamscore[fi^1]++; - f->grab_tick = server_tick(); + m_aTeamscore[fi^1]++; + F->m_GrabTick = Server()->Tick(); } - f->at_stand = 0; - f->carrying_character = close_characters[i]; - f->carrying_character->player->score += 1; + + F->m_AtStand = 0; + F->m_pCarryingCCharacter = apCloseCCharacters[i]; + F->m_pCarryingCCharacter->GetPlayer()->m_Score += 1; dbg_msg("game", "flag_grab player='%d:%s'", - f->carrying_character->player->client_id, - server_clientname(f->carrying_character->player->client_id)); + F->m_pCarryingCCharacter->GetPlayer()->GetCID(), + Server()->ClientName(F->m_pCarryingCCharacter->GetPlayer()->GetCID())); for(int c = 0; c < MAX_CLIENTS; c++) { - if(!game.players[c]) + if(!GameServer()->m_apPlayers[c]) continue; - if(game.players[c]->team == fi) - game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c]->client_id); + if(GameServer()->m_apPlayers[c]->GetTeam() == fi) + GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, GameServer()->m_apPlayers[c]->GetCID()); else - game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c]->client_id); + GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, GameServer()->m_apPlayers[c]->GetCID()); } break; } } - if(!f->carrying_character && !f->at_stand) + if(!F->m_pCarryingCCharacter && !F->m_AtStand) { - if(server_tick() > f->drop_tick + server_tickspeed()*30) + if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30) { - game.create_sound_global(SOUND_CTF_RETURN); - f->reset(); + GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); + F->Reset(); } else { - f->vel.y += game.world.core.tuning.gravity; - move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f); + F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity; + GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->m_PhysSize, F->m_PhysSize), 0.5f); } } } @@ -190,39 +207,36 @@ void GAMECONTROLLER_CTF::tick() } // Flag -FLAG::FLAG(int _team) -: ENTITY(NETOBJTYPE_FLAG) +CFlag::CFlag(CGameWorld *pGameWorld, int Team) +: CEntity(pGameWorld, NETOBJTYPE_FLAG) { - team = _team; - proximity_radius = phys_size; - carrying_character = 0x0; - grab_tick = 0; - - reset(); + m_Team = Team; + m_ProximityRadius = m_PhysSize; + m_pCarryingCCharacter = 0x0; + m_GrabTick = 0; - // TODO: should this be done here? - game.world.insert_entity(this); + Reset(); } -void FLAG::reset() +void CFlag::Reset() { - carrying_character = 0x0; - at_stand = 1; - pos = stand_pos; - vel = vec2(0,0); - grab_tick = 0; + m_pCarryingCCharacter = 0x0; + m_AtStand = 1; + m_Pos = m_StandPos; + m_Vel = vec2(0,0); + m_GrabTick = 0; } -void FLAG::snap(int snapping_client) +void CFlag::Snap(int SnappingClient) { - NETOBJ_FLAG *flag = (NETOBJ_FLAG *)snap_new_item(NETOBJTYPE_FLAG, team, sizeof(NETOBJ_FLAG)); - flag->x = (int)pos.x; - flag->y = (int)pos.y; - flag->team = team; - flag->carried_by = -1; + CNetObj_Flag *pFlag = (CNetObj_Flag *)Server()->SnapNewItem(NETOBJTYPE_FLAG, m_Team, sizeof(CNetObj_Flag)); + pFlag->m_X = (int)m_Pos.x; + pFlag->m_Y = (int)m_Pos.y; + pFlag->m_Team = m_Team; + pFlag->m_CarriedBy = -1; - if(at_stand) - flag->carried_by = -2; - else if(carrying_character && carrying_character->player) - flag->carried_by = carrying_character->player->client_id; + if(m_AtStand) + pFlag->m_CarriedBy = -2; + else if(m_pCarryingCCharacter && m_pCarryingCCharacter->GetPlayer()) + pFlag->m_CarriedBy = m_pCarryingCCharacter->GetPlayer()->GetCID(); } diff --git a/src/game/server/gamemodes/ctf.h b/src/game/server/gamemodes/ctf.h new file mode 100644 index 00000000..b86ad688 --- /dev/null +++ b/src/game/server/gamemodes/ctf.h @@ -0,0 +1,38 @@ +#ifndef GAME_SERVER_GAMEMODES_CTF_H +#define GAME_SERVER_GAMEMODES_CTF_H +#include <game/server/gamecontroller.h> +#include <game/server/entity.h> + +class CGameControllerCTF : public IGameController +{ +public: + class CFlag *m_apFlags[2]; + + CGameControllerCTF(class CGameContext *pGameServer); + virtual bool CanBeMovedOnBalance(int Cid); + virtual void Tick(); + + virtual bool OnEntity(int Index, vec2 Pos); + virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); +}; + +// TODO: move to seperate file +class CFlag : public CEntity +{ +public: + static const int m_PhysSize = 14; + CCharacter *m_pCarryingCCharacter; + vec2 m_Vel; + vec2 m_StandPos; + + int m_Team; + int m_AtStand; + int m_DropTick; + int m_GrabTick; + + CFlag(CGameWorld *pGameWorld, int Team); + + virtual void Reset(); + virtual void Snap(int SnappingClient); +}; +#endif diff --git a/src/game/server/gamemodes/ctf.hpp b/src/game/server/gamemodes/ctf.hpp deleted file mode 100644 index 67a098a4..00000000 --- a/src/game/server/gamemodes/ctf.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#include <game/server/gamecontroller.hpp> -#include <game/server/entity.hpp> - -class GAMECONTROLLER_CTF : public GAMECONTROLLER -{ -public: - class FLAG *flags[2]; - - GAMECONTROLLER_CTF(); - virtual void tick(); - - virtual bool on_entity(int index, vec2 pos); - virtual int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon); -}; - -// TODO: move to seperate file -class FLAG : public ENTITY -{ -public: - static const int phys_size = 14; - CHARACTER *carrying_character; - vec2 vel; - vec2 stand_pos; - - int team; - int at_stand; - int drop_tick; - int grab_tick; - - FLAG(int _team); - - virtual void reset(); - virtual void snap(int snapping_client); -}; diff --git a/src/game/server/gamemodes/dm.cpp b/src/game/server/gamemodes/dm.cpp index 15c0b987..173ef5fd 100644 --- a/src/game/server/gamemodes/dm.cpp +++ b/src/game/server/gamemodes/dm.cpp @@ -1,14 +1,15 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include "dm.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include "dm.h" -GAMECONTROLLER_DM::GAMECONTROLLER_DM() +CGameControllerDM::CGameControllerDM(class CGameContext *pGameServer) +: IGameController(pGameServer) { - gametype = "DM"; + m_pGameType = "DM"; } -void GAMECONTROLLER_DM::tick() +void CGameControllerDM::Tick() { - do_player_score_wincheck(); - GAMECONTROLLER::tick(); + DoPlayerScoreWincheck(); + IGameController::Tick(); } diff --git a/src/game/server/gamemodes/dm.h b/src/game/server/gamemodes/dm.h new file mode 100644 index 00000000..f2854680 --- /dev/null +++ b/src/game/server/gamemodes/dm.h @@ -0,0 +1,11 @@ +#ifndef GAME_SERVER_GAMEMODES_DM_H +#define GAME_SERVER_GAMEMODES_DM_H +#include <game/server/gamecontroller.h> + +class CGameControllerDM : public IGameController +{ +public: + CGameControllerDM(class CGameContext *pGameServer); + virtual void Tick(); +}; +#endif diff --git a/src/game/server/gamemodes/dm.hpp b/src/game/server/gamemodes/dm.hpp deleted file mode 100644 index 6fb25f61..00000000 --- a/src/game/server/gamemodes/dm.hpp +++ /dev/null @@ -1,10 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#include <game/server/gamecontroller.hpp> - -class GAMECONTROLLER_DM : public GAMECONTROLLER -{ -public: - GAMECONTROLLER_DM(); - virtual void tick(); -}; diff --git a/src/game/server/gamemodes/mod.cpp b/src/game/server/gamemodes/mod.cpp index 87b37411..44d0effc 100644 --- a/src/game/server/gamemodes/mod.cpp +++ b/src/game/server/gamemodes/mod.cpp @@ -1,20 +1,21 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include "mod.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include "mod.h" -GAMECONTROLLER_MOD::GAMECONTROLLER_MOD() +CGameControllerMOD::CGameControllerMOD(class CGameContext *pGameServer) +: IGameController(pGameServer) { // Exchange this to a string that identifies your game mode. // DM, TDM and CTF are reserved for teeworlds original modes. - gametype = "MOD"; + m_pGameType = "MOD"; - //game_flags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode + //m_GameFlags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode } -void GAMECONTROLLER_MOD::tick() +void CGameControllerMOD::Tick() { // this is the main part of the gamemode, this function is run every tick - do_player_score_wincheck(); // checks for winners, no teams version - //do_team_score_wincheck(); // checks for winners, two teams version + DoPlayerScoreWincheck(); // checks for winners, no teams version + //DoTeamScoreWincheck(); // checks for winners, two teams version - GAMECONTROLLER::tick(); + IGameController::Tick(); } diff --git a/src/game/server/gamemodes/mod.h b/src/game/server/gamemodes/mod.h new file mode 100644 index 00000000..86dff78b --- /dev/null +++ b/src/game/server/gamemodes/mod.h @@ -0,0 +1,14 @@ +#ifndef GAME_SERVER_GAMEMODES_MOD_H +#define GAME_SERVER_GAMEMODES_MOD_H +#include <game/server/gamecontroller.h> + +// you can subclass GAMECONTROLLER_CTF, GAMECONTROLLER_TDM etc if you want +// todo a modification with their base as well. +class CGameControllerMOD : public IGameController +{ +public: + CGameControllerMOD(class CGameContext *pGameServer); + virtual void Tick(); + // add more virtual functions here if you wish +}; +#endif diff --git a/src/game/server/gamemodes/mod.hpp b/src/game/server/gamemodes/mod.hpp deleted file mode 100644 index 9915a615..00000000 --- a/src/game/server/gamemodes/mod.hpp +++ /dev/null @@ -1,13 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#include <game/server/gamecontroller.hpp> - -// you can subclass GAMECONTROLLER_CTF, GAMECONTROLLER_TDM etc if you want -// todo a modification with their base as well. -class GAMECONTROLLER_MOD : public GAMECONTROLLER -{ -public: - GAMECONTROLLER_MOD(); - virtual void tick(); - // add more virtual functions here if you wish -}; diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp index 72605000..b54e3ac0 100644 --- a/src/game/server/gamemodes/tdm.cpp +++ b/src/game/server/gamemodes/tdm.cpp @@ -1,34 +1,33 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <engine/e_server_interface.h> -#include <game/server/entities/character.hpp> -#include <game/server/player.hpp> -#include "tdm.hpp" +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include <game/server/entities/character.h> +#include <game/server/player.h> +#include "tdm.h" -GAMECONTROLLER_TDM::GAMECONTROLLER_TDM() +CGameControllerTDM::CGameControllerTDM(class CGameContext *pGameServer) : IGameController(pGameServer) { - gametype = "TDM"; - game_flags = GAMEFLAG_TEAMS; + m_pGameType = "TDM"; + m_GameFlags = GAMEFLAG_TEAMS; } -int GAMECONTROLLER_TDM::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon) +int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon) { - GAMECONTROLLER::on_character_death(victim, killer, weapon); + IGameController::OnCharacterDeath(pVictim, pKiller, Weapon); - if(weapon != WEAPON_GAME) + if(Weapon != WEAPON_GAME) { // do team scoring - if(killer == victim->player || killer->team == victim->player->team) - teamscore[killer->team&1]--; // klant arschel + if(pKiller == pVictim->GetPlayer() || pKiller->GetTeam() == pVictim->GetPlayer()->GetTeam()) + m_aTeamscore[pKiller->GetTeam()&1]--; // klant arschel else - teamscore[killer->team&1]++; // good shit + m_aTeamscore[pKiller->GetTeam()&1]++; // good shit } return 0; } -void GAMECONTROLLER_TDM::tick() +void CGameControllerTDM::Tick() { - do_team_score_wincheck(); - GAMECONTROLLER::tick(); + DoTeamScoreWincheck(); + IGameController::Tick(); } diff --git a/src/game/server/gamemodes/tdm.h b/src/game/server/gamemodes/tdm.h new file mode 100644 index 00000000..2d149456 --- /dev/null +++ b/src/game/server/gamemodes/tdm.h @@ -0,0 +1,13 @@ +#ifndef GAME_SERVER_GAMEMODES_TDM_H +#define GAME_SERVER_GAMEMODES_TDM_H +#include <game/server/gamecontroller.h> + +class CGameControllerTDM : public IGameController +{ +public: + CGameControllerTDM(class CGameContext *pGameServer); + + int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); + virtual void Tick(); +}; +#endif diff --git a/src/game/server/gamemodes/tdm.hpp b/src/game/server/gamemodes/tdm.hpp deleted file mode 100644 index 51c47ca5..00000000 --- a/src/game/server/gamemodes/tdm.hpp +++ /dev/null @@ -1,12 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - -#include <game/server/gamecontroller.hpp> - -class GAMECONTROLLER_TDM : public GAMECONTROLLER -{ -public: - GAMECONTROLLER_TDM(); - - int on_character_death(class CHARACTER *victim, class PLAYER *killer, int weapon); - virtual void tick(); -}; diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 9e76f14b..42c19487 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -1,217 +1,226 @@ -#include "gameworld.hpp" -#include "entity.hpp" -#include "gamecontext.hpp" +#include "gameworld.h" +#include "entity.h" +#include "gamecontext.h" ////////////////////////////////////////////////// // game world ////////////////////////////////////////////////// -GAMEWORLD::GAMEWORLD() +CGameWorld::CGameWorld() { - paused = false; - reset_requested = false; - first_entity = 0x0; + m_pGameServer = 0x0; + m_pServer = 0x0; + + m_Paused = false; + m_ResetRequested = false; + m_pFirstEntity = 0x0; for(int i = 0; i < NUM_ENT_TYPES; i++) - first_entity_types[i] = 0; + m_apFirstEntityTypes[i] = 0; } -GAMEWORLD::~GAMEWORLD() +CGameWorld::~CGameWorld() { // delete all entities - while(first_entity) - delete first_entity; + while(m_pFirstEntity) + delete m_pFirstEntity; +} + +void CGameWorld::SetGameServer(CGameContext *pGameServer) +{ + m_pGameServer = pGameServer; + m_pServer = m_pGameServer->Server(); } -ENTITY *GAMEWORLD::find_first(int type) +CEntity *CGameWorld::FindFirst(int Type) { - return first_entity_types[type]; + return m_apFirstEntityTypes[Type]; } -int GAMEWORLD::find_entities(vec2 pos, float radius, ENTITY **ents, int max, int type) +int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type) { - int num = 0; - for(ENTITY *ent = (type<0) ? first_entity : first_entity_types[type]; - ent; ent = (type<0) ? ent->next_entity : ent->next_type_entity) + int Num = 0; + for(CEntity *pEnt = (Type<0) ? m_pFirstEntity : m_apFirstEntityTypes[Type]; + pEnt; pEnt = (Type<0) ? pEnt->m_pNextEntity : pEnt->m_pNextTypeEntity) { - if(distance(ent->pos, pos) < radius+ent->proximity_radius) + if(distance(pEnt->m_Pos, Pos) < Radius+pEnt->m_ProximityRadius) { - ents[num] = ent; - num++; - if(num == max) + ppEnts[Num] = pEnt; + Num++; + if(Num == Max) break; } } - return num; + return Num; } -void GAMEWORLD::insert_entity(ENTITY *ent) +void CGameWorld::InsertEntity(CEntity *pEnt) { - ENTITY *cur = first_entity; - while(cur) + CEntity *pCur = m_pFirstEntity; + while(pCur) { - dbg_assert(cur != ent, "err"); - cur = cur->next_entity; + dbg_assert(pCur != pEnt, "err"); + pCur = pCur->m_pNextEntity; } // insert it - if(first_entity) - first_entity->prev_entity = ent; - ent->next_entity = first_entity; - ent->prev_entity = 0x0; - first_entity = ent; + if(m_pFirstEntity) + m_pFirstEntity->m_pPrevEntity = pEnt; + pEnt->m_pNextEntity = m_pFirstEntity; + pEnt->m_pPrevEntity = 0x0; + m_pFirstEntity = pEnt; // into typelist aswell - if(first_entity_types[ent->objtype]) - first_entity_types[ent->objtype]->prev_type_entity = ent; - ent->next_type_entity = first_entity_types[ent->objtype]; - ent->prev_type_entity = 0x0; - first_entity_types[ent->objtype] = ent; + if(m_apFirstEntityTypes[pEnt->m_Objtype]) + m_apFirstEntityTypes[pEnt->m_Objtype]->m_pPrevTypeEntity = pEnt; + pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_Objtype]; + pEnt->m_pPrevTypeEntity = 0x0; + m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt; } -void GAMEWORLD::destroy_entity(ENTITY *ent) +void CGameWorld::DestroyEntity(CEntity *pEnt) { - ent->marked_for_destroy = true; + pEnt->m_MarkedForDestroy = true; } -void GAMEWORLD::remove_entity(ENTITY *ent) +void CGameWorld::RemoveEntity(CEntity *pEnt) { // not in the list - if(!ent->next_entity && !ent->prev_entity && first_entity != ent) + if(!pEnt->m_pNextEntity && !pEnt->m_pPrevEntity && m_pFirstEntity != pEnt) return; // remove - if(ent->prev_entity) - ent->prev_entity->next_entity = ent->next_entity; + if(pEnt->m_pPrevEntity) + pEnt->m_pPrevEntity->m_pNextEntity = pEnt->m_pNextEntity; else - first_entity = ent->next_entity; - if(ent->next_entity) - ent->next_entity->prev_entity = ent->prev_entity; + m_pFirstEntity = pEnt->m_pNextEntity; + if(pEnt->m_pNextEntity) + pEnt->m_pNextEntity->m_pPrevEntity = pEnt->m_pPrevEntity; - if(ent->prev_type_entity) - ent->prev_type_entity->next_type_entity = ent->next_type_entity; + if(pEnt->m_pPrevTypeEntity) + pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity; else - first_entity_types[ent->objtype] = ent->next_type_entity; - if(ent->next_type_entity) - ent->next_type_entity->prev_type_entity = ent->prev_type_entity; - - ent->next_entity = 0; - ent->prev_entity = 0; - ent->next_type_entity = 0; - ent->prev_type_entity = 0; + m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt->m_pNextTypeEntity; + if(pEnt->m_pNextTypeEntity) + pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity; + + pEnt->m_pNextEntity = 0; + pEnt->m_pPrevEntity = 0; + pEnt->m_pNextTypeEntity = 0; + pEnt->m_pPrevTypeEntity = 0; } // -void GAMEWORLD::snap(int snapping_client) +void CGameWorld::Snap(int SnappingClient) { - for(ENTITY *ent = first_entity; ent; ent = ent->next_entity) - ent->snap(snapping_client); + for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) + pEnt->Snap(SnappingClient); } -void GAMEWORLD::reset() +void CGameWorld::Reset() { // reset all entities - for(ENTITY *ent = first_entity; ent; ent = ent->next_entity) - ent->reset(); - remove_entities(); + for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) + pEnt->Reset(); + RemoveEntities(); - game.controller->post_reset(); - remove_entities(); + GameServer()->m_pController->PostReset(); + RemoveEntities(); - reset_requested = false; + m_ResetRequested = false; } -void GAMEWORLD::remove_entities() +void CGameWorld::RemoveEntities() { // destroy objects marked for destruction - ENTITY *ent = first_entity; - while(ent) + CEntity *pEnt = m_pFirstEntity; + while(pEnt) { - ENTITY *next = ent->next_entity; - if(ent->marked_for_destroy) + CEntity *pNext = pEnt->m_pNextEntity; + if(pEnt->m_MarkedForDestroy) { - remove_entity(ent); - ent->destroy(); + RemoveEntity(pEnt); + pEnt->Destroy(); } - ent = next; + pEnt = pNext; } } -void GAMEWORLD::tick() +void CGameWorld::Tick() { - if(reset_requested) - reset(); + if(m_ResetRequested) + Reset(); - if(!paused) + if(!m_Paused) { - if(game.controller->is_force_balanced()) - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, "Teams have been balanced"); + if(GameServer()->m_pController->IsForceBalanced()) + GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced"); // update all objects - for(ENTITY *ent = first_entity; ent; ent = ent->next_entity) - ent->tick(); + for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) + pEnt->Tick(); - for(ENTITY *ent = first_entity; ent; ent = ent->next_entity) - ent->tick_defered(); + for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) + pEnt->TickDefered(); } - remove_entities(); + RemoveEntities(); } // TODO: should be more general -CHARACTER *GAMEWORLD::intersect_character(vec2 pos0, vec2 pos1, float radius, vec2& new_pos, ENTITY *notthis) +CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2& NewPos, CEntity *pNotThis) { // Find other players - float closest_len = distance(pos0, pos1) * 100.0f; - vec2 line_dir = normalize(pos1-pos0); - CHARACTER *closest = 0; + float ClosestLen = distance(Pos0, Pos1) * 100.0f; + vec2 LineDir = normalize(Pos1-Pos0); + CCharacter *pClosest = 0; - CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER); - for(; p; p = (CHARACTER *)p->typenext()) + CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); + for(; p; p = (CCharacter *)p->TypeNext()) { - if(p == notthis) + if(p == pNotThis) continue; - vec2 intersect_pos = closest_point_on_line(pos0, pos1, p->pos); - float len = distance(p->pos, intersect_pos); - if(len < CHARACTER::phys_size+radius) + vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos); + float Len = distance(p->m_Pos, IntersectPos); + if(Len < p->m_ProximityRadius+Radius) { - if(len < closest_len) + if(Len < ClosestLen) { - new_pos = intersect_pos; - closest_len = len; - closest = p; + NewPos = IntersectPos; + ClosestLen = Len; + pClosest = p; } } } - return closest; + return pClosest; } -CHARACTER *GAMEWORLD::closest_character(vec2 pos, float radius, ENTITY *notthis) +CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotThis) { // Find other players - float closest_range = radius*2; - CHARACTER *closest = 0; + float ClosestRange = Radius*2; + CCharacter *pClosest = 0; - CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER); - for(; p; p = (CHARACTER *)p->typenext()) + CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER); + for(; p; p = (CCharacter *)p->TypeNext()) { - if(p == notthis) + if(p == pNotThis) continue; - float len = distance(pos, p->pos); - if(len < CHARACTER::phys_size+radius) + float Len = distance(Pos, p->m_Pos); + if(Len < p->m_ProximityRadius+Radius) { - if(len < closest_range) + if(Len < ClosestRange) { - closest_range = len; - closest = p; + ClosestRange = Len; + pClosest = p; } } } - return closest; + return pClosest; } diff --git a/src/game/server/gameworld.hpp b/src/game/server/gameworld.h index 4757ad67..2d1cc4be 100644 --- a/src/game/server/gameworld.hpp +++ b/src/game/server/gameworld.h @@ -1,20 +1,20 @@ #ifndef GAME_SERVER_GAMEWORLD_H #define GAME_SERVER_GAMEWORLD_H -#include <game/gamecore.hpp> +#include <game/gamecore.h> -class ENTITY; -class CHARACTER; +class CEntity; +class CCharacter; /* Class: Game World Tracks all entities in the game. Propagates tick and snap calls to all entities. */ -class GAMEWORLD +class CGameWorld { - void reset(); - void remove_entities(); + void Reset(); + void RemoveEntities(); enum { @@ -22,19 +22,27 @@ class GAMEWORLD }; // TODO: two lists seams kinda not good, shouldn't be needed - ENTITY *first_entity; - ENTITY *first_entity_types[NUM_ENT_TYPES]; + CEntity *m_pFirstEntity; + CEntity *m_apFirstEntityTypes[NUM_ENT_TYPES]; + + class CGameContext *m_pGameServer; + class IServer *m_pServer; public: - bool reset_requested; - bool paused; - WORLD_CORE core; + class CGameContext *GameServer() { return m_pGameServer; } + class IServer *Server() { return m_pServer; } + + bool m_ResetRequested; + bool m_Paused; + CWorldCore m_Core; + + CGameWorld(); + ~CGameWorld(); - GAMEWORLD(); - ~GAMEWORLD(); + void SetGameServer(CGameContext *pGameServer); - ENTITY *find_first() { return first_entity; } - ENTITY *find_first(int type); + CEntity *FindFirst() { return m_pFirstEntity; } + CEntity *FindFirst(int Type); /* Function: find_entities @@ -51,37 +59,37 @@ public: Returns: Number of entities found and added to the ents array. */ - int find_entities(vec2 pos, float radius, ENTITY **ents, int max, int type = -1); + int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type = -1); /* - Function: interserct_character - Finds the closest character that intersects the line. + Function: interserct_CCharacter + Finds the closest CCharacter that intersects the line. Arguments: pos0 - Start position pos2 - End position - radius - How for from the line the character is allowed to be. + radius - How for from the line the CCharacter is allowed to be. new_pos - Intersection position notthis - Entity to ignore intersecting with Returns: Returns a pointer to the closest hit or NULL of there is no intersection. */ - class CHARACTER *intersect_character(vec2 pos0, vec2 pos1, float radius, vec2 &new_pos, class ENTITY *notthis = 0); + class CCharacter *IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, class CEntity *pNotThis = 0); /* - Function: closest_character - Finds the closest character to a specific point. + Function: closest_CCharacter + Finds the closest CCharacter to a specific point. Arguments: pos - The center position. - radius - How far off the character is allowed to be + radius - How far off the CCharacter is allowed to be notthis - Entity to ignore Returns: - Returns a pointer to the closest character or NULL if no character is close enough. + Returns a pointer to the closest CCharacter or NULL if no CCharacter is close enough. */ - class CHARACTER *closest_character(vec2 pos, float radius, ENTITY *notthis); + class CCharacter *ClosestCharacter(vec2 Pos, float Radius, CEntity *ppNotThis); /* Function: insert_entity @@ -90,7 +98,7 @@ public: Arguments: entity - Entity to add */ - void insert_entity(ENTITY *entity); + void InsertEntity(CEntity *pEntity); /* Function: remove_entity @@ -99,7 +107,7 @@ public: Arguments: entity - Entity to remove */ - void remove_entity(ENTITY *entity); + void RemoveEntity(CEntity *pEntity); /* Function: destroy_entity @@ -108,7 +116,7 @@ public: Arguments: entity - Entity to destroy */ - void destroy_entity(ENTITY *entity); + void DestroyEntity(CEntity *pEntity); /* Function: snap @@ -119,7 +127,7 @@ public: snapping_client - ID of the client which snapshot is being created. */ - void snap(int snapping_client); + void Snap(int SnappingClient); /* Function: tick @@ -127,7 +135,7 @@ public: the world to the next tick. */ - void tick(); + void Tick(); }; #endif diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp deleted file mode 100644 index 89c95f79..00000000 --- a/src/game/server/hooks.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <base/math.hpp> - -#include <engine/e_config.h> -#include <engine/e_server_interface.h> -#include <engine/e_memheap.h> - -#include <game/version.hpp> -#include <game/collision.hpp> -#include <game/layers.hpp> - -#include <game/gamecore.hpp> - -#include "gamecontext.hpp" -#include "gamemodes/dm.hpp" -#include "gamemodes/tdm.hpp" -#include "gamemodes/ctf.hpp" -#include "gamemodes/mod.hpp" - -TUNING_PARAMS tuning; - -static void check_pure_tuning() -{ - // might not be created yet during start up - if(!game.controller) - return; - - if( strcmp(game.controller->gametype, "DM")==0 || - strcmp(game.controller->gametype, "TDM")==0 || - strcmp(game.controller->gametype, "CTF")==0) - { - TUNING_PARAMS p; - if(memcmp(&p, &tuning, sizeof(TUNING_PARAMS)) != 0) - { - dbg_msg("server", "resetting tuning due to pure server"); - tuning = p; - } - } -} - -struct VOTEOPTION -{ - VOTEOPTION *next; - VOTEOPTION *prev; - char command[1]; -}; - -static HEAP *voteoption_heap = 0; -static VOTEOPTION *voteoption_first = 0; -static VOTEOPTION *voteoption_last = 0; - -void send_tuning_params(int cid) -{ - check_pure_tuning(); - - msg_pack_start(NETMSGTYPE_SV_TUNEPARAMS, MSGFLAG_VITAL); - int *params = (int *)&tuning; - for(unsigned i = 0; i < sizeof(tuning)/sizeof(int); i++) - msg_pack_int(params[i]); - msg_pack_end(); - server_send_msg(cid); -} - -// Server hooks -void mods_client_direct_input(int client_id, void *input) -{ - if(!game.world.paused) - game.players[client_id]->on_direct_input((NETOBJ_PLAYER_INPUT *)input); -} - -void mods_client_predicted_input(int client_id, void *input) -{ - if(!game.world.paused) - game.players[client_id]->on_predicted_input((NETOBJ_PLAYER_INPUT *)input); -} - -// Server hooks -void mods_tick() -{ - check_pure_tuning(); - - game.tick(); - -#ifdef CONF_DEBUG - if(config.dbg_dummies) - { - for(int i = 0; i < config.dbg_dummies ; i++) - { - NETOBJ_PLAYER_INPUT input = {0}; - input.direction = (i&1)?-1:1; - game.players[MAX_CLIENTS-i-1]->on_predicted_input(&input); - } - } -#endif -} - -void mods_snap(int client_id) -{ - game.snap(client_id); -} - -void mods_client_enter(int client_id) -{ - //game.world.insert_entity(&game.players[client_id]); - game.players[client_id]->respawn(); - dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id)); - - - char buf[512]; - str_format(buf, sizeof(buf), "%s entered and joined the %s", server_clientname(client_id), game.controller->get_team_name(game.players[client_id]->team)); - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); - - dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), game.players[client_id]->team); -} - -void mods_connected(int client_id) -{ - game.players[client_id] = new(client_id) PLAYER(client_id); - //game.players[client_id].init(client_id); - //game.players[client_id].client_id = client_id; - - // Check which team the player should be on - if(config.sv_tournament_mode) - game.players[client_id]->team = -1; - else - game.players[client_id]->team = game.controller->get_auto_team(client_id); - - (void) game.controller->check_team_balance(); - - // send motd - NETMSG_SV_MOTD msg; - msg.message = config.sv_motd; - msg.pack(MSGFLAG_VITAL); - server_send_msg(client_id); -} - -void mods_client_drop(int client_id) -{ - game.abort_vote_kick_on_disconnect(client_id); - game.players[client_id]->on_disconnect(); - delete game.players[client_id]; - game.players[client_id] = 0; - - (void) game.controller->check_team_balance(); -} - -/*static bool is_separator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; } - -static const char *liststr_find(const char *str, const char *needle) -{ - int needle_len = strlen(needle); - while(*str) - { - int wordlen = 0; - while(str[wordlen] && !is_separator(str[wordlen])) - wordlen++; - - if(wordlen == needle_len && strncmp(str, needle, needle_len) == 0) - return str; - - str += wordlen+1; - } - - return 0; -}*/ - -void mods_message(int msgtype, int client_id) -{ - void *rawmsg = netmsg_secure_unpack(msgtype); - PLAYER *p = game.players[client_id]; - - if(!rawmsg) - { - dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on()); - return; - } - - if(msgtype == NETMSGTYPE_CL_SAY) - { - NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg; - int team = msg->team; - if(team) - team = p->team; - else - team = GAMECONTEXT::CHAT_ALL; - - if(config.sv_spamprotection && p->last_chat+time_freq() > time_get()) - return; - - p->last_chat = time_get(); - - game.send_chat(client_id, team, msg->message); - } - else if(msgtype == NETMSGTYPE_CL_CALLVOTE) - { - int64 now = time_get(); - if(game.vote_closetime) - { - game.send_chat_target(client_id, "Wait for current vote to end before calling a new one."); - return; - } - - int64 timeleft = p->last_votecall + time_freq()*60 - now; - if(timeleft > 0) - { - char chatmsg[512] = {0}; - str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1); - game.send_chat_target(client_id, chatmsg); - return; - } - - char chatmsg[512] = {0}; - char desc[512] = {0}; - char cmd[512] = {0}; - NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg; - if(str_comp_nocase(msg->type, "option") == 0) - { - VOTEOPTION *option = voteoption_first; - while(option) - { - if(str_comp_nocase(msg->value, option->command) == 0) - { - str_format(chatmsg, sizeof(chatmsg), "%s called vote to change server option '%s'", server_clientname(client_id), option->command); - str_format(desc, sizeof(desc), "%s", option->command); - str_format(cmd, sizeof(cmd), "%s", option->command); - break; - } - - option = option->next; - } - - if(!option) - { - str_format(chatmsg, sizeof(chatmsg), "'%s' isn't an option on this server", msg->value); - game.send_chat_target(client_id, chatmsg); - return; - } - } - else if(str_comp_nocase(msg->type, "kick") == 0) - { - if(!config.sv_vote_kick) - { - game.send_chat_target(client_id, "Server does not allow voting to kick players"); - return; - } - - int kick_id = atoi(msg->value); - if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id]) - { - game.send_chat_target(client_id, "Invalid client id to kick"); - return; - } - - str_format(chatmsg, sizeof(chatmsg), "%s called for vote to kick '%s'", server_clientname(client_id), server_clientname(kick_id)); - str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id)); - str_format(cmd, sizeof(cmd), "kick %d", kick_id); - if (!config.sv_vote_kick_bantime) - str_format(cmd, sizeof(cmd), "kick %d", kick_id); - else - str_format(cmd, sizeof(cmd), "ban %d %d", kick_id, config.sv_vote_kick_bantime); - } - - if(cmd[0]) - { - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg); - game.start_vote(desc, cmd); - p->vote = 1; - game.vote_creator = client_id; - p->last_votecall = now; - game.send_vote_status(-1); - } - } - else if(msgtype == NETMSGTYPE_CL_VOTE) - { - if(!game.vote_closetime) - return; - - if(p->vote == 0) - { - NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg; - p->vote = msg->vote; - game.send_vote_status(-1); - } - } - else if (msgtype == NETMSGTYPE_CL_SETTEAM && !game.world.paused) - { - NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg; - - if(config.sv_spamprotection && p->last_setteam+time_freq()*3 > time_get()) - return; - - // Switch team on given client and kill/respawn him - if(game.controller->can_join_team(msg->team, client_id)) - { - if(game.controller->can_change_team(p, msg->team)) - { - p->last_setteam = time_get(); - p->set_team(msg->team); - (void) game.controller->check_team_balance(); - } - else - game.send_broadcast("Teams must be balanced, please join other team", client_id); - } - else - { - char buf[128]; - str_format(buf, sizeof(buf), "Only %d active players are allowed", config.sv_max_clients-config.sv_spectator_slots); - game.send_broadcast(buf, client_id); - } - } - else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO) - { - NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg; - - if(config.sv_spamprotection && p->last_changeinfo+time_freq()*5 > time_get()) - return; - - p->last_changeinfo = time_get(); - - p->use_custom_color = msg->use_custom_color; - p->color_body = msg->color_body; - p->color_feet = msg->color_feet; - - // check for invalid chars - unsigned char *name = (unsigned char *)msg->name; - while (*name) - { - if(*name < 32) - *name = ' '; - name++; - } - - // copy old name - char oldname[MAX_NAME_LENGTH]; - str_copy(oldname, server_clientname(client_id), MAX_NAME_LENGTH); - - server_setclientname(client_id, msg->name); - if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(oldname, server_clientname(client_id)) != 0) - { - char chattext[256]; - str_format(chattext, sizeof(chattext), "%s changed name to %s", oldname, server_clientname(client_id)); - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chattext); - } - - // set skin - str_copy(p->skin_name, msg->skin, sizeof(p->skin_name)); - - game.controller->on_player_info_change(p); - - if(msgtype == NETMSGTYPE_CL_STARTINFO) - { - // send vote options - NETMSG_SV_VOTE_CLEAROPTIONS clearmsg; - clearmsg.pack(MSGFLAG_VITAL); - server_send_msg(client_id); - VOTEOPTION *current = voteoption_first; - while(current) - { - NETMSG_SV_VOTE_OPTION optionmsg; - optionmsg.command = current->command; - optionmsg.pack(MSGFLAG_VITAL); - server_send_msg(client_id); - current = current->next; - } - - // send tuning parameters to client - send_tuning_params(client_id); - - // - NETMSG_SV_READYTOENTER m; - m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH); - server_send_msg(client_id); - } - } - else if (msgtype == NETMSGTYPE_CL_EMOTICON && !game.world.paused) - { - NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg; - - if(config.sv_spamprotection && p->last_emote+time_freq()*3 > time_get()) - return; - - p->last_emote = time_get(); - - game.send_emoticon(client_id, msg->emoticon); - } - else if (msgtype == NETMSGTYPE_CL_KILL && !game.world.paused) - { - if(p->last_kill+time_freq()*3 > time_get()) - return; - - p->last_kill = time_get(); - p->kill_character(WEAPON_SELF); - p->respawn_tick = server_tick()+server_tickspeed()*3; - } -} - -static void con_tune_param(void *result, void *user_data) -{ - const char *param_name = console_arg_string(result, 0); - float new_value = console_arg_float(result, 1); - - if(tuning.set(param_name, new_value)) - { - dbg_msg("tuning", "%s changed to %.2f", param_name, new_value); - send_tuning_params(-1); - } - else - console_print("No such tuning parameter"); -} - -static void con_tune_reset(void *result, void *user_data) -{ - TUNING_PARAMS p; - tuning = p; - send_tuning_params(-1); - console_print("tuning reset"); -} - -static void con_tune_dump(void *result, void *user_data) -{ - for(int i = 0; i < tuning.num(); i++) - { - float v; - tuning.get(i, &v); - dbg_msg("tuning", "%s %.2f", tuning.names[i], v); - } -} - - -static void con_change_map(void *result, void *user_data) -{ - game.controller->change_map(console_arg_string(result, 0)); -} - -static void con_restart(void *result, void *user_data) -{ - if(console_arg_num(result)) - game.controller->do_warmup(console_arg_int(result, 0)); - else - game.controller->startround(); -} - -static void con_broadcast(void *result, void *user_data) -{ - game.send_broadcast(console_arg_string(result, 0), -1); -} - -static void con_say(void *result, void *user_data) -{ - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, console_arg_string(result, 0)); -} - -static void con_set_team(void *result, void *user_data) -{ - int client_id = clamp(console_arg_int(result, 0), 0, (int)MAX_CLIENTS); - int team = clamp(console_arg_int(result, 1), -1, 1); - - dbg_msg("", "%d %d", client_id, team); - - if(!game.players[client_id]) - return; - - game.players[client_id]->set_team(team); - (void) game.controller->check_team_balance(); -} - -static void con_addvote(void *result, void *user_data) -{ - int len = strlen(console_arg_string(result, 0)); - - if(!voteoption_heap) - voteoption_heap = memheap_create(); - - VOTEOPTION *option = (VOTEOPTION *)memheap_allocate(voteoption_heap, sizeof(VOTEOPTION) + len); - option->next = 0; - option->prev = voteoption_last; - if(option->prev) - option->prev->next = option; - voteoption_last = option; - if(!voteoption_first) - voteoption_first = option; - - mem_copy(option->command, console_arg_string(result, 0), len+1); - dbg_msg("server", "added option '%s'", option->command); -} - -static void con_vote(void *result, void *user_data) -{ - if(str_comp_nocase(console_arg_string(result, 0), "yes") == 0) - game.vote_enforce = GAMECONTEXT::VOTE_ENFORCE_YES; - else if(str_comp_nocase(console_arg_string(result, 0), "no") == 0) - game.vote_enforce = GAMECONTEXT::VOTE_ENFORCE_NO; - dbg_msg("server", "forcing vote %s", console_arg_string(result, 0)); -} - -void mods_console_init() -{ - MACRO_REGISTER_COMMAND("tune", "si", CFGFLAG_SERVER, con_tune_param, 0, ""); - MACRO_REGISTER_COMMAND("tune_reset", "", CFGFLAG_SERVER, con_tune_reset, 0, ""); - MACRO_REGISTER_COMMAND("tune_dump", "", CFGFLAG_SERVER, con_tune_dump, 0, ""); - - MACRO_REGISTER_COMMAND("change_map", "r", CFGFLAG_SERVER, con_change_map, 0, ""); - MACRO_REGISTER_COMMAND("restart", "?i", CFGFLAG_SERVER, con_restart, 0, ""); - MACRO_REGISTER_COMMAND("broadcast", "r", CFGFLAG_SERVER, con_broadcast, 0, ""); - MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_say, 0, ""); - MACRO_REGISTER_COMMAND("set_team", "ii", CFGFLAG_SERVER, con_set_team, 0, ""); - - MACRO_REGISTER_COMMAND("addvote", "r", CFGFLAG_SERVER, con_addvote, 0, ""); - MACRO_REGISTER_COMMAND("vote", "r", CFGFLAG_SERVER, con_vote, 0, ""); -} - -void mods_init() -{ - //if(!data) /* only load once */ - //data = load_data_from_memory(internal_data); - - for(int i = 0; i < NUM_NETOBJTYPES; i++) - snap_set_staticsize(i, netobj_get_size(i)); - - layers_init(); - col_init(); - - // reset everything here - //world = new GAMEWORLD; - //players = new PLAYER[MAX_CLIENTS]; - - // select gametype - if(strcmp(config.sv_gametype, "mod") == 0) - game.controller = new GAMECONTROLLER_MOD; - else if(strcmp(config.sv_gametype, "ctf") == 0) - game.controller = new GAMECONTROLLER_CTF; - else if(strcmp(config.sv_gametype, "tdm") == 0) - game.controller = new GAMECONTROLLER_TDM; - else - game.controller = new GAMECONTROLLER_DM; - - // setup core world - //for(int i = 0; i < MAX_CLIENTS; i++) - // game.players[i].core.world = &game.world.core; - - // create all entities from the game layer - MAPITEM_LAYER_TILEMAP *tmap = layers_game_layer(); - TILE *tiles = (TILE *)map_get_data(tmap->data); - - /* - num_spawn_points[0] = 0; - num_spawn_points[1] = 0; - num_spawn_points[2] = 0; - */ - - for(int y = 0; y < tmap->height; y++) - { - for(int x = 0; x < tmap->width; x++) - { - int index = tiles[y*tmap->width+x].index; - - if(index >= ENTITY_OFFSET) - { - vec2 pos(x*32.0f+16.0f, y*32.0f+16.0f); - game.controller->on_entity(index-ENTITY_OFFSET, pos); - } - } - } - - //game.world.insert_entity(game.controller); - -#ifdef CONF_DEBUG - if(config.dbg_dummies) - { - for(int i = 0; i < config.dbg_dummies ; i++) - { - mods_connected(MAX_CLIENTS-i-1); - mods_client_enter(MAX_CLIENTS-i-1); - if(game.controller->is_teamplay()) - game.players[MAX_CLIENTS-i-1]->team = i&1; - } - } -#endif -} - -void mods_shutdown() -{ - delete game.controller; - game.controller = 0; - game.clear(); -} - -void mods_presnap() {} -void mods_postsnap() -{ - game.events.clear(); -} - -const char *mods_net_version() { return GAME_NETVERSION; } -const char *mods_version() { return GAME_VERSION; } diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index a0a2b051..0eb61cac 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -1,183 +1,185 @@ #include <new> +#include "player.h" -#include <engine/e_server_interface.h> -#include "player.hpp" -#include "gamecontext.hpp" +MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS) -MACRO_ALLOC_POOL_ID_IMPL(PLAYER, MAX_CLIENTS) - -PLAYER::PLAYER(int client_id) +IServer *CPlayer::Server() const { return m_pGameServer->Server(); } + +CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team) { - respawn_tick = server_tick(); - character = 0; - this->client_id = client_id; + m_pGameServer = pGameServer; + m_RespawnTick = Server()->Tick(); + m_DieTick = Server()->Tick(); + Character = 0; + this->m_ClientID = CID; + m_Team = GameServer()->m_pController->ClampTeam(Team); } -PLAYER::~PLAYER() +CPlayer::~CPlayer() { - delete character; - character = 0; + delete Character; + Character = 0; } -void PLAYER::tick() +void CPlayer::Tick() { - server_setclientscore(client_id, score); + Server()->SetClientScore(m_ClientID, m_Score); // do latency stuff { - CLIENT_INFO info; - if(server_getclientinfo(client_id, &info)) + IServer::CClientInfo Info; + if(Server()->GetClientInfo(m_ClientID, &Info)) { - latency.accum += info.latency; - latency.accum_max = max(latency.accum_max, info.latency); - latency.accum_min = min(latency.accum_min, info.latency); + m_Latency.m_Accum += Info.m_Latency; + m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency); + m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency); } - - if(server_tick()%server_tickspeed() == 0) + // each second + if(Server()->Tick()%Server()->TickSpeed() == 0) { - latency.avg = latency.accum/server_tickspeed(); - latency.max = latency.accum_max; - latency.min = latency.accum_min; - latency.accum = 0; - latency.accum_min = 1000; - latency.accum_max = 0; + m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed(); + m_Latency.m_Max = m_Latency.m_AccumMax; + m_Latency.m_Min = m_Latency.m_AccumMin; + m_Latency.m_Accum = 0; + m_Latency.m_AccumMin = 1000; + m_Latency.m_AccumMax = 0; } } - if(!character && die_tick+server_tickspeed()*3 <= server_tick()) - spawning = true; + if(!Character && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick()) + m_Spawning = true; - if(character) + if(Character) { - if(character->alive) + if(Character->IsAlive()) { - view_pos = character->pos; + m_ViewPos = Character->m_Pos; } else { - delete character; - character = 0; + delete Character; + Character = 0; } } - else if(spawning && respawn_tick <= server_tick()) - try_respawn(); + else if(m_Spawning && m_RespawnTick <= Server()->Tick()) + TryRespawn(); } -void PLAYER::snap(int snapping_client) +void CPlayer::Snap(int SnappingClient) { - NETOBJ_CLIENT_INFO *client_info = (NETOBJ_CLIENT_INFO *)snap_new_item(NETOBJTYPE_CLIENT_INFO, client_id, sizeof(NETOBJ_CLIENT_INFO)); - str_to_ints(&client_info->name0, 6, server_clientname(client_id)); - str_to_ints(&client_info->skin0, 6, skin_name); - client_info->use_custom_color = use_custom_color; - client_info->color_body = color_body; - client_info->color_feet = color_feet; - - NETOBJ_PLAYER_INFO *info = (NETOBJ_PLAYER_INFO *)snap_new_item(NETOBJTYPE_PLAYER_INFO, client_id, sizeof(NETOBJ_PLAYER_INFO)); - - info->latency = latency.min; - info->latency_flux = latency.max-latency.min; - info->local = 0; - info->cid = client_id; - info->score = score; - info->team = team; - - if(client_id == snapping_client) - info->local = 1; + CNetObj_ClientInfo *ClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo))); + StrToInts(&ClientInfo->m_Name0, 6, Server()->ClientName(m_ClientID)); + StrToInts(&ClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName); + ClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor; + ClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody; + ClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet; + + CNetObj_PlayerInfo *Info = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo))); + + Info->m_Latency = m_Latency.m_Min; + Info->m_LatencyFlux = m_Latency.m_Max-m_Latency.m_Min; + Info->m_Local = 0; + Info->m_ClientId = m_ClientID; + Info->m_Score = m_Score; + Info->m_Team = m_Team; + + if(m_ClientID == SnappingClient) + Info->m_Local = 1; } -void PLAYER::on_disconnect() +void CPlayer::OnDisconnect() { - kill_character(WEAPON_GAME); - - //game.controller->on_player_death(&game.players[client_id], 0, -1); - - char buf[512]; - str_format(buf, sizeof(buf), "%s has left the game", server_clientname(client_id)); - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); + KillCharacter(); + + if(Server()->ClientIngame(m_ClientID)) + { + char Buf[512]; + str_format(Buf, sizeof(Buf), "%s has left the game", Server()->ClientName(m_ClientID)); + GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf); - dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id)); + dbg_msg("game", "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID)); + } } -void PLAYER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input) +void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput) { - CHARACTER *chr = get_character(); - if(chr) - chr->on_predicted_input(new_input); + if(Character) + Character->OnPredictedInput(NewInput); } -void PLAYER::on_direct_input(NETOBJ_PLAYER_INPUT *new_input) +void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput) { - CHARACTER *chr = get_character(); - if(chr) - chr->on_direct_input(new_input); + if(Character) + Character->OnDirectInput(NewInput); - if(!chr && team >= 0 && (new_input->fire&1)) - spawning = true; + if(!Character && m_Team >= 0 && (NewInput->m_Fire&1)) + m_Spawning = true; - if(!chr && team == -1) - view_pos = vec2(new_input->target_x, new_input->target_y); + if(!Character && m_Team == -1) + m_ViewPos = vec2(NewInput->m_TargetX, NewInput->m_TargetY); } -CHARACTER *PLAYER::get_character() +CCharacter *CPlayer::GetCharacter() { - if(character && character->alive) - return character; + if(Character && Character->IsAlive()) + return Character; return 0; } -void PLAYER::kill_character(int weapon) +void CPlayer::KillCharacter(int Weapon) { - //CHARACTER *chr = get_character(); - if(character) + if(Character) { - character->die(client_id, weapon); - delete character; - character = 0; + Character->Die(m_ClientID, Weapon); + delete Character; + Character = 0; } } -void PLAYER::respawn() +void CPlayer::Respawn() { - if(team > -1) - spawning = true; + if(m_Team > -1) + m_Spawning = true; } -void PLAYER::set_team(int new_team) +void CPlayer::SetTeam(int Team) { // clamp the team - new_team = game.controller->clampteam(new_team); - if(team == new_team) + Team = GameServer()->m_pController->ClampTeam(Team); + if(m_Team == Team) return; - char buf[512]; - str_format(buf, sizeof(buf), "%s joined the %s", server_clientname(client_id), game.controller->get_team_name(new_team)); - game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); + char Buf[512]; + str_format(Buf, sizeof(Buf), "%s joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team)); + GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf); - kill_character(WEAPON_GAME); - team = new_team; - score = 0; - dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), team); + KillCharacter(); + m_Team = Team; + m_Score = 0; + // we got to wait 0.5 secs before respawning + m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2; + dbg_msg("game", "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team); - game.controller->on_player_info_change(game.players[client_id]); + GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]); } -void PLAYER::try_respawn() +void CPlayer::TryRespawn() { - vec2 spawnpos = vec2(100.0f, -60.0f); + vec2 SpawnPos = vec2(100.0f, -60.0f); - if(!game.controller->can_spawn(this, &spawnpos)) + if(!GameServer()->m_pController->CanSpawn(this, &SpawnPos)) return; // check if the position is occupado - ENTITY *ents[2] = {0}; - int num_ents = game.world.find_entities(spawnpos, 64, ents, 2, NETOBJTYPE_CHARACTER); + CEntity *apEnts[2] = {0}; + int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, NETOBJTYPE_CHARACTER); - if(num_ents == 0) + if(NumEnts == 0) { - spawning = false; - character = new(client_id) CHARACTER(); - character->spawn(this, spawnpos, team); - game.create_playerspawn(spawnpos); + m_Spawning = false; + Character = new(m_ClientID) CCharacter(&GameServer()->m_World); + Character->Spawn(this, SpawnPos); + GameServer()->CreatePlayerSpawn(SpawnPos); } } diff --git a/src/game/server/player.h b/src/game/server/player.h new file mode 100644 index 00000000..1b631d45 --- /dev/null +++ b/src/game/server/player.h @@ -0,0 +1,89 @@ +#ifndef GAME_SERVER_PLAYER_H +#define GAME_SERVER_PLAYER_H + +// this include should perhaps be removed +#include "entities/character.h" +#include "gamecontext.h" + +// player object +class CPlayer +{ + MACRO_ALLOC_POOL_ID() + +public: + CPlayer(CGameContext *pGameServer, int CID, int Team); + ~CPlayer(); + + void Init(int CID); + + void TryRespawn(); + void Respawn(); + void SetTeam(int Team); + int GetTeam() const { return m_Team; }; + int GetCID() const { return m_ClientID; }; + + void Tick(); + void Snap(int SnappingClient); + + void OnDirectInput(CNetObj_PlayerInput *NewInput); + void OnPredictedInput(CNetObj_PlayerInput *NewInput); + void OnDisconnect(); + + void KillCharacter(int Weapon = WEAPON_GAME); + CCharacter *GetCharacter(); + + //--------------------------------------------------------- + // this is used for snapping so we know how we can clip the view for the player + vec2 m_ViewPos; + + // + int m_Vote; + int m_VotePos; + // + int m_Last_VoteCall; + int m_Last_VoteTry; + int m_Last_Chat; + int m_Last_SetTeam; + int m_Last_ChangeInfo; + int m_Last_Emote; + int m_Last_Kill; + + // TODO: clean this up + struct + { + char m_SkinName[64]; + int m_UseCustomColor; + int m_ColorBody; + int m_ColorFeet; + } m_TeeInfos; + + int m_RespawnTick; + int m_DieTick; + int m_Score; + bool m_ForceBalanced; + +private: + CCharacter *Character; + CGameContext *m_pGameServer; + + CGameContext *GameServer() const { return m_pGameServer; } + IServer *Server() const; + + // + bool m_Spawning; + int m_ClientID; + int m_Team; + + // network latency calculations + struct + { + int m_Accum; + int m_AccumMin; + int m_AccumMax; + int m_Avg; + int m_Min; + int m_Max; + } m_Latency; +}; + +#endif diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp deleted file mode 100644 index e93aee01..00000000 --- a/src/game/server/player.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef GAME_SERVER_PLAYER_H -#define GAME_SERVER_PLAYER_H - -// this include should perhaps be removed -#include "entities/character.hpp" - -// player object -class PLAYER -{ - MACRO_ALLOC_POOL_ID() -private: - CHARACTER *character; -public: - PLAYER(int client_id); - ~PLAYER(); - - // TODO: clean this up - char skin_name[64]; - int use_custom_color; - int color_body; - int color_feet; - - int respawn_tick; - int die_tick; - // - bool spawning; - int client_id; - int team; - int score; - bool force_balanced; - - // - int vote; - int64 last_votecall; - - // - int64 last_chat; - int64 last_setteam; - int64 last_changeinfo; - int64 last_emote; - int64 last_kill; - - // network latency calculations - struct - { - int accum; - int accum_min; - int accum_max; - int avg; - int min; - int max; - } latency; - - // this is used for snapping so we know how we can clip the view for the player - vec2 view_pos; - - void init(int client_id); - - CHARACTER *get_character(); - - void kill_character(int weapon); - - void try_respawn(); - void respawn(); - void set_team(int team); - - void tick(); - void snap(int snapping_client); - - void on_direct_input(NETOBJ_PLAYER_INPUT *new_input); - void on_predicted_input(NETOBJ_PLAYER_INPUT *new_input); - void on_disconnect(); -}; - -#endif diff --git a/src/game/tuning.h b/src/game/tuning.h new file mode 100644 index 00000000..b336fcb3 --- /dev/null +++ b/src/game/tuning.h @@ -0,0 +1,46 @@ +#ifndef GAME_TUNING_H +#define GAME_TUNING_H +#undef GAME_TUNING_H // this file will be included several times + +// physics tuning +MACRO_TUNING_PARAM(GroundControlSpeed, ground_control_speed, 10.0f) +MACRO_TUNING_PARAM(GroundControlAccel, ground_control_accel, 100.0f / TicksPerSecond) +MACRO_TUNING_PARAM(GroundFriction, ground_friction, 0.5f) +MACRO_TUNING_PARAM(GroundJumpImpulse, ground_jump_impulse, 13.2f) +MACRO_TUNING_PARAM(AirJumpImpulse, air_jump_impulse, 12.0f) +MACRO_TUNING_PARAM(AirControlSpeed, air_control_speed, 250.0f / TicksPerSecond) +MACRO_TUNING_PARAM(AirControlAccel, air_control_accel, 1.5f) +MACRO_TUNING_PARAM(AirFriction, air_friction, 0.95f) +MACRO_TUNING_PARAM(HookLength, hook_length, 380.0f) +MACRO_TUNING_PARAM(HookFireSpeed, hook_fire_speed, 80.0f) +MACRO_TUNING_PARAM(HookDragAccel, hook_drag_accel, 3.0f) +MACRO_TUNING_PARAM(HookDragSpeed, hook_drag_speed, 15.0f) +MACRO_TUNING_PARAM(Gravity, gravity, 0.5f) + +MACRO_TUNING_PARAM(VelrampStart, velramp_start, 550) +MACRO_TUNING_PARAM(VelrampRange, velramp_range, 2000) +MACRO_TUNING_PARAM(VelrampCurvature, velramp_curvature, 1.4f) + +// weapon tuning +MACRO_TUNING_PARAM(GunCurvature, gun_curvature, 1.25f) +MACRO_TUNING_PARAM(GunSpeed, gun_speed, 2200.0f) +MACRO_TUNING_PARAM(GunLifetime, gun_lifetime, 2.0f) + +MACRO_TUNING_PARAM(ShotgunCurvature, shotgun_curvature, 1.25f) +MACRO_TUNING_PARAM(ShotgunSpeed, shotgun_speed, 2750.0f) +MACRO_TUNING_PARAM(ShotgunSpeeddiff, shotgun_speeddiff, 0.8f) +MACRO_TUNING_PARAM(ShotgunLifetime, shotgun_lifetime, 0.20f) + +MACRO_TUNING_PARAM(GrenadeCurvature, grenade_curvature, 7.0f) +MACRO_TUNING_PARAM(GrenadeSpeed, grenade_speed, 1000.0f) +MACRO_TUNING_PARAM(GrenadeLifetime, grenade_lifetime, 2.0f) + +MACRO_TUNING_PARAM(LaserReach, laser_reach, 800.0f) +MACRO_TUNING_PARAM(LaserBounceDelay, laser_bounce_delay, 150) +MACRO_TUNING_PARAM(LaserBounceNum, laser_bounce_num, 1) +MACRO_TUNING_PARAM(LaserBounceCost, laser_bounce_cost, 0) +MACRO_TUNING_PARAM(LaserDamage, laser_damage, 5) + +MACRO_TUNING_PARAM(PlayerCollision, player_collision, 1) +MACRO_TUNING_PARAM(PlayerHooking, player_hooking, 1) +#endif diff --git a/src/game/tuning.hpp b/src/game/tuning.hpp deleted file mode 100644 index 4554a8eb..00000000 --- a/src/game/tuning.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* physics tuning */ -MACRO_TUNING_PARAM(ground_control_speed, 10.0f) -MACRO_TUNING_PARAM(ground_control_accel, 100.0f / ticks_per_second) -MACRO_TUNING_PARAM(ground_friction, 0.5f) -MACRO_TUNING_PARAM(ground_jump_impulse, 13.2f) -MACRO_TUNING_PARAM(air_jump_impulse, 12.0f) -MACRO_TUNING_PARAM(air_control_speed, 250.0f / ticks_per_second) -MACRO_TUNING_PARAM(air_control_accel, 1.5f) -MACRO_TUNING_PARAM(air_friction, 0.95f) -MACRO_TUNING_PARAM(hook_length, 380.0f) -MACRO_TUNING_PARAM(hook_fire_speed, 80.0f) -MACRO_TUNING_PARAM(hook_drag_accel, 3.0f) -MACRO_TUNING_PARAM(hook_drag_speed, 15.0f) -MACRO_TUNING_PARAM(gravity, 0.5f) - -MACRO_TUNING_PARAM(velramp_start, 550) -MACRO_TUNING_PARAM(velramp_range, 2000) -MACRO_TUNING_PARAM(velramp_curvature, 1.4f) - -/* weapon tuning */ -MACRO_TUNING_PARAM(gun_curvature, 1.25f) -MACRO_TUNING_PARAM(gun_speed, 2200.0f) -MACRO_TUNING_PARAM(gun_lifetime, 2.0f) - -MACRO_TUNING_PARAM(shotgun_curvature, 1.25f) -MACRO_TUNING_PARAM(shotgun_speed, 2750.0f) -MACRO_TUNING_PARAM(shotgun_speeddiff, 0.8f) -MACRO_TUNING_PARAM(shotgun_lifetime, 0.20f) - -MACRO_TUNING_PARAM(grenade_curvature, 7.0f) -MACRO_TUNING_PARAM(grenade_speed, 1000.0f) -MACRO_TUNING_PARAM(grenade_lifetime, 2.0f) - -MACRO_TUNING_PARAM(laser_reach, 800.0f) -MACRO_TUNING_PARAM(laser_bounce_delay, 150) -MACRO_TUNING_PARAM(laser_bounce_num, 1) -MACRO_TUNING_PARAM(laser_bounce_cost, 0) -MACRO_TUNING_PARAM(laser_damage, 5) - -MACRO_TUNING_PARAM(player_collision, 1) -MACRO_TUNING_PARAM(player_hooking, 1) diff --git a/src/game/variables.h b/src/game/variables.h new file mode 100644 index 00000000..6a247671 --- /dev/null +++ b/src/game/variables.h @@ -0,0 +1,79 @@ +#ifndef GAME_VARIABLES_H +#define GAME_VARIABLES_H +#undef GAME_VARIABLES_H // this file will be included several times + + +// client +MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") +MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show nameplates") +MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show nameplats disregarding of distance") +MACRO_CONFIG_INT(ClAutoswitchWeapons, cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Auto switch weapon on pickup") + +MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter") + +MACRO_CONFIG_INT(ClAirjumpindicator, cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") +MACRO_CONFIG_INT(ClThreadsoundloading, cl_threadsoundloading, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") + +MACRO_CONFIG_INT(ClWarningTeambalance, cl_warning_teambalance, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Warn about team balance") + +MACRO_CONFIG_INT(ClMouseDeadzone, cl_mouse_deadzone, 300, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") +MACRO_CONFIG_INT(ClMouseFollowfactor, cl_mouse_followfactor, 60, 0, 200, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") +MACRO_CONFIG_INT(ClMouseMaxDistance, cl_mouse_max_distance, 800, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") + +MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") + +MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") + +MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") +MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day") + +MACRO_CONFIG_STR(ClVersionServer, cl_version_server, 100, "version.teeworlds.com", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Server to use to check for new versions") + +MACRO_CONFIG_STR(ClLanguagefile, cl_languagefile, 255, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "What language file to use") + +MACRO_CONFIG_INT(PlayerUseCustomColor, player_use_custom_color, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors") +MACRO_CONFIG_INT(PlayerColorBody, player_color_body, 65408, 0, 0xFFFFFF, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player body color") +MACRO_CONFIG_INT(PlayerColorFeet, player_color_feet, 65408, 0, 0xFFFFFF, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player feet color") +MACRO_CONFIG_STR(PlayerSkin, player_skin, 64, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") + +MACRO_CONFIG_INT(UiPage, ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") +MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page") +MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 25, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") +MACRO_CONFIG_INT(UiScale, ui_scale, 100, 1, 100000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale") + +MACRO_CONFIG_INT(UiColorHue, ui_color_hue, 160, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color hue") +MACRO_CONFIG_INT(UiColorSat, ui_color_sat, 70, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color saturation") +MACRO_CONFIG_INT(UiColorLht, ui_color_lht, 175, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color lightness") +MACRO_CONFIG_INT(UiColorAlpha, ui_color_alpha, 228, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface alpha") + +MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping") + +// server +MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warpup before round starts") +MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients") +MACRO_CONFIG_INT(SvTeamdamage, sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage") +MACRO_CONFIG_STR(SvMaprotation, sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between") +MACRO_CONFIG_INT(SvRoundsPerMap, sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating") +MACRO_CONFIG_INT(SvPowerups, sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja") +MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)") +MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)") +MACRO_CONFIG_STR(SvGametype, sv_gametype, 32, "dm", CFGFLAG_SERVER, "Game type (dm, tdm, ctf)") +MACRO_CONFIG_INT(SvTournamentMode, sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator") +MACRO_CONFIG_INT(SvSpamprotection, sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection") + +MACRO_CONFIG_INT(SvSpectatorSlots, sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators") +MACRO_CONFIG_INT(SvTeambalanceTime, sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams") + +MACRO_CONFIG_INT(SvVoteKick, sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players") +MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick") +MACRO_CONFIG_INT(SvVoteScorelimit, sv_vote_scorelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change score limit") +MACRO_CONFIG_INT(SvVoteTimelimit, sv_vote_timelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change time limit") + +// debug +#ifdef CONF_DEBUG // this one can crash the server if not used correctly + MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "") +#endif + +MACRO_CONFIG_INT(DbgFocus, dbg_focus, 0, 0, 1, CFGFLAG_CLIENT, "") +MACRO_CONFIG_INT(DbgTuning, dbg_tuning, 0, 0, 1, CFGFLAG_CLIENT, "") +#endif diff --git a/src/game/variables.hpp b/src/game/variables.hpp deleted file mode 100644 index e0d9fe31..00000000 --- a/src/game/variables.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ - - -/* client */ -MACRO_CONFIG_INT(cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements") -MACRO_CONFIG_INT(cl_nameplates, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show nameplates") -MACRO_CONFIG_INT(cl_nameplates_always, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show nameplats disregarding of distance") -MACRO_CONFIG_INT(cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Auto switch weapon on pickup") - -MACRO_CONFIG_INT(cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter") - -MACRO_CONFIG_INT(cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") -MACRO_CONFIG_INT(cl_threadsoundloading, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") - -MACRO_CONFIG_INT(cl_warning_teambalance, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Warn about team balance") - -MACRO_CONFIG_INT(cl_mouse_deadzone, 300, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") -MACRO_CONFIG_INT(cl_mouse_followfactor, 60, 0, 200, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") -MACRO_CONFIG_INT(cl_mouse_max_distance, 800, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") - -MACRO_CONFIG_INT(ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") - -MACRO_CONFIG_INT(cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") - -MACRO_CONFIG_INT(cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") -MACRO_CONFIG_INT(cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day") - -MACRO_CONFIG_STR(cl_version_server, 100, "version.teeworlds.com", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Server to use to check for new versions") - -MACRO_CONFIG_STR(cl_languagefile, 255, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "What language file to use") - -MACRO_CONFIG_INT(player_use_custom_color, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toggles usage of custom colors") -MACRO_CONFIG_INT(player_color_body, 65408, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player body color") -MACRO_CONFIG_INT(player_color_feet, 65408, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player feet color") -MACRO_CONFIG_STR(player_skin, 64, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") - -MACRO_CONFIG_INT(ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") -MACRO_CONFIG_STR(ui_server_address, 128, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") -MACRO_CONFIG_INT(ui_scale, 100, 1, 100000, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale") - -MACRO_CONFIG_INT(ui_color_hue, 160, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color hue") -MACRO_CONFIG_INT(ui_color_sat, 70, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color saturation") -MACRO_CONFIG_INT(ui_color_lht, 175, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface color lightness") -MACRO_CONFIG_INT(ui_color_alpha, 228, 0, 255, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface alpha") - -MACRO_CONFIG_INT(gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping") - -/* server */ -MACRO_CONFIG_INT(sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warpup before round starts") -MACRO_CONFIG_STR(sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients") -MACRO_CONFIG_INT(sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage") -MACRO_CONFIG_STR(sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between") -MACRO_CONFIG_INT(sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating") -MACRO_CONFIG_INT(sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja") -MACRO_CONFIG_INT(sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)") -MACRO_CONFIG_INT(sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)") -MACRO_CONFIG_STR(sv_gametype, 32, "dm", CFGFLAG_SERVER, "Game type (dm, tdm, ctf)") -MACRO_CONFIG_INT(sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator") -MACRO_CONFIG_INT(sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection") - -MACRO_CONFIG_INT(sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators") -MACRO_CONFIG_INT(sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams") - -MACRO_CONFIG_INT(sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players") -MACRO_CONFIG_INT(sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick") -MACRO_CONFIG_INT(sv_vote_scorelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change score limit") -MACRO_CONFIG_INT(sv_vote_timelimit, 0, 0, 1, CFGFLAG_SERVER, "Allow voting to change time limit") - -/* debug */ -#ifdef CONF_DEBUG /* this one can crash the server if not used correctly */ - MACRO_CONFIG_INT(dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "") -#endif - -MACRO_CONFIG_INT(dbg_focus, 0, 0, 1, CFGFLAG_CLIENT, "") -MACRO_CONFIG_INT(dbg_tuning, 0, 0, 1, CFGFLAG_CLIENT, "") diff --git a/src/game/version.h b/src/game/version.h new file mode 100644 index 00000000..0fe22c95 --- /dev/null +++ b/src/game/version.h @@ -0,0 +1,8 @@ +#ifndef GAME_VERSION_H +#define GAME_VERSION_H +#include "generated/nethash.c" +#define GAME_VERSION "trunk" +//#define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH +// TODO: hash forced during refactoring. Remove later on +#define GAME_NETVERSION "0.5 b67d1f1a1eea234e" +#endif diff --git a/src/game/version.hpp b/src/game/version.hpp deleted file mode 100644 index 2692752c..00000000 --- a/src/game/version.hpp +++ /dev/null @@ -1,4 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include "generated/nethash.c" -#define GAME_VERSION "trunk" -#define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH |