Untitled

From Anonymous, 3 Years ago, written in Plain Text, viewed 112 times.
URL https://paste.bugabuse.net/view/11231558 Embed
Download Paste or View Raw
  1. diff -Naur ../teeworlds/src/base/system.c src/base/system.c
  2. --- ../teeworlds/src/base/system.c      2012-06-26 16:53:53.280861226 +1000
  3. +++ src/base/system.c   2012-07-08 19:42:32.918259340 +1000
  4. @@ -90,7 +90,15 @@
  5.         char *msg;
  6.         int i, len;
  7.  
  8. -       str_format(str, sizeof(str), "[x][%s]: ", (int)time(0), sys);
  9. +       time_t rawtime;
  10. +               struct tm * timeinfo;
  11. +               char timestr [80];
  12. +
  13. +               time ( &rawtime );
  14. +               timeinfo = localtime ( &rawtime );
  15. +              
  16. +               strftime (timestr,sizeof(timestr),"%y-%m-%d %H:%M:%S",timeinfo);
  17. +       str_format(str, sizeof(str), "[%s][%s]: ", timestr, sys);
  18.         len = strlen(str);
  19.         msg = (char *)str + len;
  20.  
  21. @@ -505,20 +513,18 @@
  22.  #endif
  23.  }
  24.  
  25. -#if !defined(CONF_PLATFORM_MACOSX)
  26. -       #if defined(CONF_FAMILY_UNIX)
  27. -       void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
  28. -       void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
  29. -       void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
  30. -       void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
  31. -       #elif defined(CONF_FAMILY_WINDOWS)
  32. -       void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
  33. -       void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, 0L); }
  34. -       void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
  35. -       void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
  36. -       #else
  37. -               #error not implemented on this platform
  38. -       #endif
  39. +#if defined(CONF_FAMILY_UNIX)
  40. +void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
  41. +void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
  42. +void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
  43. +void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
  44. +#elif defined(CONF_FAMILY_WINDOWS)
  45. +void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
  46. +void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, 0L); }
  47. +void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
  48. +void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
  49. +#else
  50. +       #error not implemented on this platform
  51.  #endif
  52.  
  53.  
  54. @@ -905,7 +911,6 @@
  55.         NETSOCKET sock = invalid_socket;
  56.         NETADDR tmpbindaddr = bindaddr;
  57.         int broadcast = 1;
  58. -       int recvsize = 65536;
  59.  
  60.         if(bindaddr.type&NETTYPE_IPV4)
  61.         {
  62. @@ -920,13 +925,13 @@
  63.                 {
  64.                         sock.type |= NETTYPE_IPV4;
  65.                         sock.ipv4sock = socket;
  66. +               }
  67.  
  68. -                       /* set broadcast */
  69. -                       setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
  70. +               /* set non-blocking */
  71. +               net_set_non_blocking(sock);
  72.  
  73. -                       /* set receive buffer size */
  74. -                       setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
  75. -               }
  76. +               /* set boardcast */
  77. +               setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
  78.         }
  79.  
  80.         if(bindaddr.type&NETTYPE_IPV6)
  81. @@ -942,18 +947,15 @@
  82.                 {
  83.                         sock.type |= NETTYPE_IPV6;
  84.                         sock.ipv6sock = socket;
  85. +               }
  86.  
  87. -                       /* set broadcast */
  88. -                       setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
  89. +               /* set non-blocking */
  90. +               net_set_non_blocking(sock);
  91.  
  92. -                       /* set receive buffer size */
  93. -                       setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
  94. -               }
  95. +               /* set boardcast */
  96. +               setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
  97.         }
  98.  
  99. -       /* set non-blocking */
  100. -       net_set_non_blocking(sock);
  101. -
  102.         /* return */
  103.         return sock;
  104.  }
  105. @@ -1687,10 +1689,10 @@
  106.                                 return result;
  107.                 }
  108.  
  109. -               if(tolower(*a) != tolower(*b))
  110. +               if(*a != *b)
  111.                         break;
  112.         }
  113. -       return tolower(*a) - tolower(*b);
  114. +       return *a - *b;
  115.  }
  116.  
  117.  const char *str_find_nocase(const char *haystack, const char *needle)
  118. diff -Naur ../teeworlds/src/base/system.h src/base/system.h
  119. --- ../teeworlds/src/base/system.h      2012-06-26 16:53:53.280861226 +1000
  120. +++ src/base/system.h   2012-07-08 19:42:32.782259024 +1000
  121. @@ -403,22 +403,20 @@
  122.  
  123.  /* Group: Semaphores */
  124.  
  125. -#if !defined(CONF_PLATFORM_MACOSX)
  126. -       #if defined(CONF_FAMILY_UNIX)
  127. -               #include <semaphore.h>
  128. -               typedef sem_t SEMAPHORE;
  129. -       #elif defined(CONF_FAMILY_WINDOWS)
  130. -               typedef void* SEMAPHORE;
  131. -       #else
  132. -               #error missing sempahore implementation
  133. -       #endif
  134. -
  135. -       void semaphore_init(SEMAPHORE *sem);
  136. -       void semaphore_wait(SEMAPHORE *sem);
  137. -       void semaphore_signal(SEMAPHORE *sem);
  138. -       void semaphore_destroy(SEMAPHORE *sem);
  139. +#if defined(CONF_FAMILY_UNIX)
  140. +       #include <semaphore.h>
  141. +       typedef sem_t SEMAPHORE;
  142. +#elif defined(CONF_FAMILY_WINDOWS)
  143. +       typedef void* SEMAPHORE;
  144. +#else
  145. +       #error missing sempahore implementation
  146.  #endif
  147.  
  148. +void semaphore_init(SEMAPHORE *sem);
  149. +void semaphore_wait(SEMAPHORE *sem);
  150. +void semaphore_signal(SEMAPHORE *sem);
  151. +void semaphore_destroy(SEMAPHORE *sem);
  152. +
  153.  /* Group: Timer */
  154.  #ifdef __GNUC__
  155.  /* if compiled with -pedantic-errors it will complain about long
  156. diff -Naur ../teeworlds/src/base/tl/threading.h src/base/tl/threading.h
  157. --- ../teeworlds/src/base/tl/threading.h        2012-06-26 16:53:53.284860687 +1000
  158. +++ src/base/tl/threading.h     2012-07-08 19:42:32.782259024 +1000
  159. @@ -58,21 +58,15 @@
  160.         #error missing atomic implementation for this compiler
  161.  #endif
  162.  
  163. -#if defined(CONF_PLATFORM_MACOSX)
  164. -       /*
  165. -               use semaphore provided by SDL on macosx
  166. -       */
  167. -#else
  168. -       class semaphore
  169. -       {
  170. -               SEMAPHORE sem;
  171. -       public:
  172. -               semaphore() { semaphore_init(&sem); }
  173. -               ~semaphore() { semaphore_destroy(&sem); }
  174. -               void wait() { semaphore_wait(&sem); }
  175. -               void signal() { semaphore_signal(&sem); }
  176. -       };
  177. -#endif
  178. +class semaphore
  179. +{
  180. +       SEMAPHORE sem;
  181. +public:
  182. +       semaphore() { semaphore_init(&sem); }
  183. +       ~semaphore() { semaphore_destroy(&sem); }
  184. +       void wait() { semaphore_wait(&sem); }
  185. +       void signal() { semaphore_signal(&sem); }
  186. +};
  187.  
  188.  class lock
  189.  {
  190. diff -Naur ../teeworlds/src/base/vmath.h src/base/vmath.h
  191. --- ../teeworlds/src/base/vmath.h       2012-06-26 16:53:53.284860687 +1000
  192. +++ src/base/vmath.h    2012-07-08 19:42:32.782259024 +1000
  193. @@ -5,8 +5,6 @@
  194.  
  195.  #include <math.h>
  196.  
  197. -#include "math.h"      // mix
  198. -
  199.  // ------------------------------------
  200.  
  201.  template<typename T>
  202. diff -Naur ../teeworlds/src/engine/client/backend_sdl.cpp src/engine/client/backend_sdl.cpp
  203. --- ../teeworlds/src/engine/client/backend_sdl.cpp      2012-07-08 00:31:07.981176576 +1000
  204. +++ src/engine/client/backend_sdl.cpp   2012-07-08 19:42:32.782259024 +1000
  205. @@ -388,7 +388,7 @@
  206.  
  207.  // ------------ CGraphicsBackend_SDL_OpenGL
  208.  
  209. -int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags)
  210. +int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags)
  211.  {
  212.         if(!SDL_WasInit(SDL_INIT_VIDEO))
  213.         {
  214. @@ -407,13 +407,6 @@
  215.         const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
  216.         SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
  217.  
  218. -       // use current resolution as default
  219. -       if(*Width == 0 || *Height == 0)
  220. -       {
  221. -               *Width = pInfo->current_w;
  222. -               *Height = pInfo->current_h;
  223. -       }
  224. -
  225.         // set flags
  226.         int SdlFlags = SDL_OPENGL;
  227.         if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE)
  228. @@ -427,13 +420,6 @@
  229.         if(pInfo->blit_hw) // ignore_convention
  230.                 SdlFlags |= SDL_HWACCEL;
  231.  
  232. -       dbg_assert(!(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
  233. -               || !(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN),
  234. -               "only one of borderless and fullscreen may be activated at the same time");
  235. -
  236. -       if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
  237. -               SdlFlags |= SDL_NOFRAME;
  238. -
  239.         if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
  240.                 SdlFlags |= SDL_FULLSCREEN;
  241.  
  242. @@ -450,13 +436,13 @@
  243.         }
  244.  
  245.         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  246. -       SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0);
  247. +       SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&CCommandBuffer::INITFLAG_VSYNC ? 1 : 0);
  248.  
  249.         // set caption
  250.         SDL_WM_SetCaption(pName, pName);
  251.  
  252.         // create window
  253. -       m_pScreenSurface = SDL_SetVideoMode(*Width, *Height, 0, SdlFlags);
  254. +       m_pScreenSurface = SDL_SetVideoMode(Width, Height, 0, SdlFlags);
  255.         if(!m_pScreenSurface)
  256.         {
  257.                 dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
  258. diff -Naur ../teeworlds/src/engine/client/backend_sdl.h src/engine/client/backend_sdl.h
  259. --- ../teeworlds/src/engine/client/backend_sdl.h        2012-06-26 16:53:53.284860687 +1000
  260. +++ src/engine/client/backend_sdl.h     2012-07-08 19:42:32.786259184 +1000
  261. @@ -30,16 +30,6 @@
  262.  
  263.         #include <AGL/agl.h>
  264.  
  265. -       class semaphore
  266. -       {
  267. -               SDL_sem *sem;
  268. -       public:
  269. -               semaphore() { sem = SDL_CreateSemaphore(0); }
  270. -               ~semaphore() { SDL_DestroySemaphore(sem); }
  271. -               void wait() { SDL_SemWait(sem); }
  272. -               void signal() { SDL_SemPost(sem); }
  273. -       };
  274. -
  275.         struct SGLContext
  276.         {
  277.                 AGLContext m_Context;
  278. @@ -198,7 +188,7 @@
  279.         ICommandProcessor *m_pProcessor;
  280.         SGLContext m_GLContext;
  281.  public:
  282. -       virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags);
  283. +       virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags);
  284.         virtual int Shutdown();
  285.  
  286.         virtual void Minimize();
  287. diff -Naur ../teeworlds/src/engine/client/client.cpp src/engine/client/client.cpp
  288. --- ../teeworlds/src/engine/client/client.cpp   2012-06-26 16:53:53.288862243 +1000
  289. +++ src/engine/client/client.cpp        2012-07-08 19:42:32.786259184 +1000
  290. @@ -1028,8 +1028,6 @@
  291.                         const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES);
  292.                         int MapCrc = Unpacker.GetInt();
  293.                         int MapSize = Unpacker.GetInt();
  294. -                       int MapChunkNum = Unpacker.GetInt();
  295. -                       int MapChunkSize = Unpacker.GetInt();
  296.                         const char *pError = 0;
  297.  
  298.                         if(Unpacker.Error())
  299. @@ -1039,14 +1037,13 @@
  300.                         if(!m_MapChecker.IsMapValid(pMap, MapCrc, MapSize))
  301.                                 pError = "invalid standard map";
  302.  
  303. -                       // protect the player from nasty map names
  304. -                       for(int i = 0; pMap[i]; i++)
  305. +                       for(int i = 0; pMap[i]; i++) // protect the player from nasty map names
  306.                         {
  307.                                 if(pMap[i] == '/' || pMap[i] == '\\')
  308.                                         pError = "strange character in map name";
  309.                         }
  310.  
  311. -                       if(MapSize <= 0)
  312. +                       if(MapSize < 0)
  313.                                 pError = "invalid map size";
  314.  
  315.                         if(pError)
  316. @@ -1062,50 +1059,52 @@
  317.                                 }
  318.                                 else
  319.                                 {
  320. -                                       // start map download
  321.                                         str_format(m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename), "downloadedmaps/%s_x.map", pMap, MapCrc);
  322.  
  323.                                         char aBuf[256];
  324.                                         str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilename);
  325.                                         m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf);
  326.  
  327. +                                       m_MapdownloadChunk = 0;
  328.                                         str_copy(m_aMapdownloadName, pMap, sizeof(m_aMapdownloadName));
  329.                                         if(m_MapdownloadFile)
  330.                                                 io_close(m_MapdownloadFile);
  331.                                         m_MapdownloadFile = Storage()->OpenFile(m_aMapdownloadFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
  332. -                                       m_MapdownloadChunk = 0;
  333. -                                       m_MapdownloadChunkNum = MapChunkNum;
  334. -                                       m_MapDownloadChunkSize = MapChunkSize;
  335.                                         m_MapdownloadCrc = MapCrc;
  336.                                         m_MapdownloadTotalsize = MapSize;
  337.                                         m_MapdownloadAmount = 0;
  338.  
  339. -                                       // request first chunk package of map data
  340.                                         CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA);
  341. +                                       Msg.AddInt(m_MapdownloadChunk);
  342.                                         SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
  343.  
  344.                                         if(g_Config.m_Debug)
  345. -                                               m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested first chunk package");
  346. +                                       {
  347. +                                               str_format(aBuf, sizeof(aBuf), "requested chunk %d", m_MapdownloadChunk);
  348. +                                               m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", aBuf);
  349. +                                       }
  350.                                 }
  351.                         }
  352.                 }
  353.                 else if(Msg == NETMSG_MAP_DATA)
  354.                 {
  355. -                       if(!m_MapdownloadFile)
  356. -                               return;
  357. -
  358. -                       int Size = min(m_MapDownloadChunkSize, m_MapdownloadTotalsize-m_MapdownloadAmount);
  359. +                       int Last = Unpacker.GetInt();
  360. +                       int MapCRC = Unpacker.GetInt();
  361. +                       int Chunk = Unpacker.GetInt();
  362. +                       int Size = Unpacker.GetInt();
  363.                         const unsigned char *pData = Unpacker.GetRaw(Size);
  364. -                       if(Unpacker.Error())
  365. +
  366. +                       // check fior errors
  367. +                       if(Unpacker.Error() || Size <= 0 || MapCRC != m_MapdownloadCrc || Chunk != m_MapdownloadChunk || !m_MapdownloadFile)
  368.                                 return;
  369. -
  370. +
  371.                         io_write(m_MapdownloadFile, pData, Size);
  372. -                       ++m_MapdownloadChunk;
  373. +
  374.                         m_MapdownloadAmount += Size;
  375.  
  376. -                       if(m_MapdownloadAmount == m_MapdownloadTotalsize)
  377. +                       if(Last)
  378.                         {
  379. -                               // map download complete
  380. +                               const char *pError;
  381.                                 m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map");
  382.  
  383.                                 if(m_MapdownloadFile)
  384. @@ -1115,7 +1114,7 @@
  385.                                 m_MapdownloadTotalsize = -1;
  386.  
  387.                                 // load map
  388. -                               const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadCrc);
  389. +                               pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, m_MapdownloadCrc);
  390.                                 if(!pError)
  391.                                 {
  392.                                         m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
  393. @@ -1124,14 +1123,21 @@
  394.                                 else
  395.                                         DisconnectWithReason(pError);
  396.                         }
  397. -                       else if(m_MapdownloadChunk%m_MapdownloadChunkNum == 0)
  398. +                       else
  399.                         {
  400. -                               // request next chunk package of map data
  401. +                               // request new chunk
  402. +                               m_MapdownloadChunk++;
  403. +
  404.                                 CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA);
  405. +                               Msg.AddInt(m_MapdownloadChunk);
  406.                                 SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
  407.  
  408.                                 if(g_Config.m_Debug)
  409. -                                       m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested next chunk package");
  410. +                               {
  411. +                                       char aBuf[256];
  412. +                                       str_format(aBuf, sizeof(aBuf), "requested chunk %d", m_MapdownloadChunk);
  413. +                                       m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", aBuf);
  414. +                               }
  415.                         }
  416.                 }
  417.                 else if(Msg == NETMSG_CON_READY)
  418. @@ -1740,19 +1746,14 @@
  419.         // open socket
  420.         {
  421.                 NETADDR BindAddr;
  422. -               if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
  423. -               {
  424. -                       // got bindaddr
  425. -                       BindAddr.type = NETTYPE_ALL;
  426. -               }
  427. -               else
  428. +               if(g_Config.m_Bindaddr[0] == 0 || net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) != 0)
  429.                 {
  430.                         mem_zero(&BindAddr, sizeof(BindAddr));
  431.                         BindAddr.type = NETTYPE_ALL;
  432.                 }
  433.                 if(!m_NetClient.Open(BindAddr, 0))
  434.                 {
  435. -                       dbg_msg("client", "couldn't open socket");
  436. +                       dbg_msg("client", "couldn't start network");
  437.                         return;
  438.                 }
  439.         }
  440. diff -Naur ../teeworlds/src/engine/client/client.h src/engine/client/client.h
  441. --- ../teeworlds/src/engine/client/client.h     2012-06-26 16:53:53.288862243 +1000
  442. +++ src/engine/client/client.h  2012-07-08 19:42:32.786259184 +1000
  443. @@ -121,8 +121,6 @@
  444.         char m_aMapdownloadName[256];
  445.         IOHANDLE m_MapdownloadFile;
  446.         int m_MapdownloadChunk;
  447. -       int m_MapdownloadChunkNum;
  448. -       int m_MapDownloadChunkSize;
  449.         int m_MapdownloadCrc;
  450.         int m_MapdownloadAmount;
  451.         int m_MapdownloadTotalsize;
  452. @@ -177,6 +175,8 @@
  453.                 class CHostLookup m_VersionServeraddr;
  454.         } m_VersionInfo;
  455.  
  456. +       semaphore m_GfxRenderSemaphore;
  457. +       semaphore m_GfxStateSemaphore;
  458.         volatile int m_GfxState;
  459.         static void GraphicsThreadProxy(void *pThis) { ((CClient*)pThis)->GraphicsThread(); }
  460.         void GraphicsThread();
  461. diff -Naur ../teeworlds/src/engine/client/graphics.cpp src/engine/client/graphics.cpp
  462. --- ../teeworlds/src/engine/client/graphics.cpp 2012-07-08 00:31:07.981176576 +1000
  463. +++ src/engine/client/graphics.cpp      2012-07-08 19:42:32.786259184 +1000
  464. @@ -22,20 +22,6 @@
  465.  #include "graphics.h"
  466.  
  467.  
  468. -#if defined(CONF_PLATFORM_MACOSX)
  469. -
  470. -       class semaphore
  471. -       {
  472. -               SDL_sem *sem;
  473. -       public:
  474. -               semaphore() { sem = SDL_CreateSemaphore(0); }
  475. -               ~semaphore() { SDL_DestroySemaphore(sem); }
  476. -               void wait() { SDL_SemWait(sem); }
  477. -               void signal() { SDL_SemPost(sem); }
  478. -       };
  479. -#endif
  480. -
  481. -
  482.  static CVideoMode g_aFakeModes[] = {
  483.         {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
  484.         {720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
  485. @@ -775,19 +761,12 @@
  486.  
  487.  int CGraphics_SDL::TryInit()
  488.  {
  489. -       const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
  490. -       SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
  491. -
  492. -       // use current resolution as default
  493. -       if(g_Config.m_GfxScreenWidth == 0 || g_Config.m_GfxScreenHeight == 0)
  494. -       {
  495. -               g_Config.m_GfxScreenWidth = pInfo->current_w;
  496. -               g_Config.m_GfxScreenHeight = pInfo->current_h;
  497. -       }
  498. -
  499.         m_ScreenWidth = g_Config.m_GfxScreenWidth;
  500.         m_ScreenHeight = g_Config.m_GfxScreenHeight;
  501.  
  502. +       const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
  503. +       SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
  504. +
  505.         // set flags
  506.         int Flags = SDL_OPENGL;
  507.         if(g_Config.m_DbgResizable)
  508. @@ -801,15 +780,7 @@
  509.         if(pInfo->blit_hw) // ignore_convention
  510.                 Flags |= SDL_HWACCEL;
  511.  
  512. -       if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
  513. -       {
  514. -               dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
  515. -               g_Config.m_GfxBorderless = 0;
  516. -       }
  517. -
  518. -       if(g_Config.m_GfxBorderless)
  519. -               Flags |= SDL_NOFRAME;
  520. -       else if(g_Config.m_GfxFullscreen)
  521. +       if(g_Config.m_GfxFullscreen)
  522.                 Flags |= SDL_FULLSCREEN;
  523.  
  524.         // set gl attributes
  525. @@ -958,8 +929,7 @@
  526.  {
  527.         if(m_DoScreenshot)
  528.         {
  529. -               if(WindowActive())
  530. -                       ScreenshotDirect(m_aScreenshotName);
  531. +               ScreenshotDirect(m_aScreenshotName);
  532.                 m_DoScreenshot = false;
  533.         }
  534.  
  535. diff -Naur ../teeworlds/src/engine/client/graphics_threaded.cpp src/engine/client/graphics_threaded.cpp
  536. --- ../teeworlds/src/engine/client/graphics_threaded.cpp        2012-07-08 00:31:07.981176576 +1000
  537. +++ src/engine/client/graphics_threaded.cpp     2012-07-08 19:42:32.790259134 +1000
  538. @@ -712,18 +712,11 @@
  539.  int CGraphics_Threaded::IssueInit()
  540.  {
  541.         int Flags = 0;
  542. -       if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
  543. -       {
  544. -               dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
  545. -               g_Config.m_GfxBorderless = 0;
  546. -       }
  547. -
  548. -       if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
  549. -       else if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
  550. +       if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
  551.         if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
  552.         if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
  553.  
  554. -       return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
  555. +       return m_pBackend->Init("Teeworlds", g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
  556.  }
  557.  
  558.  int CGraphics_Threaded::InitWindow()
  559. @@ -850,8 +843,7 @@
  560.         // TODO: screenshot support
  561.         if(m_DoScreenshot)
  562.         {
  563. -               if(WindowActive())
  564. -                       ScreenshotDirect(m_aScreenshotName);
  565. +               ScreenshotDirect(m_aScreenshotName);
  566.                 m_DoScreenshot = false;
  567.         }
  568.  
  569. diff -Naur ../teeworlds/src/engine/client/graphics_threaded.h src/engine/client/graphics_threaded.h
  570. --- ../teeworlds/src/engine/client/graphics_threaded.h  2012-07-08 00:31:07.985177225 +1000
  571. +++ src/engine/client/graphics_threaded.h       2012-07-08 19:42:32.790259134 +1000
  572. @@ -98,6 +98,13 @@
  573.  
  574.         enum
  575.         {
  576. +               INITFLAG_FULLSCREEN = 1,
  577. +               INITFLAG_VSYNC = 2,
  578. +               INITFLAG_RESIZABLE = 4,
  579. +       };
  580. +
  581. +       enum
  582. +       {
  583.                 //
  584.                 PRIMTYPE_INVALID = 0,
  585.                 PRIMTYPE_LINES,
  586. @@ -293,10 +300,9 @@
  587.                 INITFLAG_FULLSCREEN = 1,
  588.                 INITFLAG_VSYNC = 2,
  589.                 INITFLAG_RESIZABLE = 4,
  590. -               INITFLAG_BORDERLESS = 8,
  591.         };
  592.  
  593. -       virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) = 0;
  594. +       virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags) = 0;
  595.         virtual int Shutdown() = 0;
  596.  
  597.         virtual void Minimize() = 0;
  598. diff -Naur ../teeworlds/src/engine/client/input.cpp src/engine/client/input.cpp
  599. --- ../teeworlds/src/engine/client/input.cpp    2012-07-08 00:31:07.985177225 +1000
  600. +++ src/engine/client/input.cpp 2012-07-08 19:28:03.322259115 +1000
  601. @@ -35,7 +35,6 @@
  602.  
  603.         m_InputCurrent = 0;
  604.         m_InputGrabbed = 0;
  605. -       m_InputDispatched = false;
  606.  
  607.         m_LastRelease = 0;
  608.         m_ReleaseDelta = -1;
  609. @@ -117,14 +116,10 @@
  610.         /*if(!input_grabbed && Graphics()->WindowActive())
  611.                 Input()->MouseModeRelative();*/
  612.  
  613. -       if(m_InputDispatched)
  614. -       {
  615. -               // clear and begin count on the other one
  616. -               m_InputCurrent^=1;
  617. -               mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
  618. -               mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
  619. -               m_InputDispatched = false;
  620. -       }
  621. +       // clear and begin count on the other one
  622. +       m_InputCurrent^=1;
  623. +       mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
  624. +       mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
  625.  
  626.         {
  627.                 int i;
  628. diff -Naur ../teeworlds/src/engine/client/serverbrowser.cpp src/engine/client/serverbrowser.cpp
  629. --- ../teeworlds/src/engine/client/serverbrowser.cpp    2012-07-08 00:31:07.985177225 +1000
  630. +++ src/engine/client/serverbrowser.cpp 2012-07-08 19:42:32.790259134 +1000
  631. @@ -86,7 +86,7 @@
  632.         CServerEntry *a = m_ppServerlist[Index1];
  633.         CServerEntry *b = m_ppServerlist[Index2];
  634.         //      make sure empty entries are listed last
  635. -       return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp_nocase(a->m_Info.m_aName, b->m_Info.m_aName) < 0 :
  636. +       return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp(a->m_Info.m_aName, b->m_Info.m_aName) < 0 :
  637.                         a->m_GotInfo ? true : false;
  638.  }
  639.  
  640. @@ -94,7 +94,7 @@
  641.  {
  642.         CServerEntry *a = m_ppServerlist[Index1];
  643.         CServerEntry *b = m_ppServerlist[Index2];
  644. -       return str_comp_nocase(a->m_Info.m_aMap, b->m_Info.m_aMap) < 0;
  645. +       return str_comp(a->m_Info.m_aMap, b->m_Info.m_aMap) < 0;
  646.  }
  647.  
  648.  bool CServerBrowser::SortComparePing(int Index1, int Index2) const
  649. @@ -108,7 +108,7 @@
  650.  {
  651.         CServerEntry *a = m_ppServerlist[Index1];
  652.         CServerEntry *b = m_ppServerlist[Index2];
  653. -       return str_comp_nocase(a->m_Info.m_aGameType, b->m_Info.m_aGameType) < 0;
  654. +       return str_comp(a->m_Info.m_aGameType, b->m_Info.m_aGameType) < 0;
  655.  }
  656.  
  657.  bool CServerBrowser::SortCompareNumPlayers(int Index1, int Index2) const
  658. @@ -154,9 +154,7 @@
  659.                 else if(g_Config.m_BrFilterPure &&
  660.                         (str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "DM") != 0 &&
  661.                         str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "TDM") != 0 &&
  662. -                       str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "CTF") != 0 &&
  663. -                       str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "SUR") != 0 &&
  664. -                       str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "LMS") != 0))
  665. +                       str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "CTF") != 0))
  666.                 {
  667.                         Filtered = 1;
  668.                 }
  669. @@ -356,6 +354,21 @@
  670.         pEntry->m_Info = Info;
  671.         pEntry->m_Info.m_Favorite = Fav;
  672.         pEntry->m_Info.m_NetAddr = pEntry->m_Addr;
  673. +
  674. +       // all these are just for nice compability
  675. +       if(pEntry->m_Info.m_aGameType[0] == '0' && pEntry->m_Info.m_aGameType[1] == 0)
  676. +               str_copy(pEntry->m_Info.m_aGameType, "DM", sizeof(pEntry->m_Info.m_aGameType));
  677. +       else if(pEntry->m_Info.m_aGameType[0] == '1' && pEntry->m_Info.m_aGameType[1] == 0)
  678. +               str_copy(pEntry->m_Info.m_aGameType, "TDM", sizeof(pEntry->m_Info.m_aGameType));
  679. +       else if(pEntry->m_Info.m_aGameType[0] == '2' && pEntry->m_Info.m_aGameType[1] == 0)
  680. +               str_copy(pEntry->m_Info.m_aGameType, "CTF", sizeof(pEntry->m_Info.m_aGameType));
  681. +
  682. +       /*if(!request)
  683. +       {
  684. +               pEntry->m_Info.latency = (time_get()-pEntry->request_time)*1000/time_freq();
  685. +               RemoveRequest(pEntry);
  686. +       }*/
  687. +
  688.         pEntry->m_GotInfo = 1;
  689.  }
  690.  
  691. @@ -482,7 +495,7 @@
  692.                 /* do the broadcast version */
  693.                 Packet.m_ClientID = -1;
  694.                 mem_zero(&Packet, sizeof(Packet));
  695. -               Packet.m_Address.type = m_pNetClient->NetType()|NETTYPE_LINK_BROADCAST;
  696. +               Packet.m_Address.type = NETTYPE_ALL|NETTYPE_LINK_BROADCAST;
  697.                 Packet.m_Flags = NETSENDFLAG_CONNLESS;
  698.                 Packet.m_DataSize = sizeof(Buffer);
  699.                 Packet.m_pData = Buffer;
  700. diff -Naur ../teeworlds/src/engine/client/text.cpp src/engine/client/text.cpp
  701. --- ../teeworlds/src/engine/client/text.cpp     2012-06-26 16:53:53.296864587 +1000
  702. +++ src/engine/client/text.cpp  2012-07-08 19:42:32.790259134 +1000
  703. @@ -639,7 +639,7 @@
  704.                                         Compare.m_Y = DrawY;
  705.                                         Compare.m_Flags &= ~TEXTFLAG_RENDER;
  706.                                         Compare.m_LineWidth = -1;
  707. -                                       TextEx(&Compare, pCurrent, Wlen);
  708. +                                       TextEx(&Compare, pText, Wlen);
  709.  
  710.                                         if(Compare.m_X-DrawX > pCursor->m_LineWidth)
  711.                                         {
  712. diff -Naur ../teeworlds/src/engine/input.h src/engine/input.h
  713. --- ../teeworlds/src/engine/input.h     2012-07-08 00:31:07.985177225 +1000
  714. +++ src/engine/input.h  2012-07-08 19:28:03.354259900 +1000
  715. @@ -38,7 +38,6 @@
  716.  
  717.         unsigned char m_aInputState[2][1024];
  718.         int m_InputCurrent;
  719. -       bool m_InputDispatched;
  720.  
  721.         int KeyWasPressed(int Key) { return m_aInputState[m_InputCurrent^1][Key]; }
  722.  
  723. @@ -52,11 +51,7 @@
  724.  
  725.         // events
  726.         int NumEvents() const { return m_NumEvents; }
  727. -       void ClearEvents()
  728. -       {
  729. -               m_NumEvents = 0;
  730. -               m_InputDispatched = true;
  731. -       }
  732. +       void ClearEvents() { m_NumEvents = 0; }
  733.         CEvent GetEvent(int Index) const
  734.         {
  735.                 if(Index < 0 || Index >= m_NumEvents)
  736. diff -Naur ../teeworlds/src/engine/server/register.cpp src/engine/server/register.cpp
  737. --- ../teeworlds/src/engine/server/register.cpp 2012-06-26 16:53:53.328861462 +1000
  738. +++ src/engine/server/register.cpp      2012-07-08 19:28:03.354259900 +1000
  739. @@ -263,7 +263,7 @@
  740.         else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWOK) &&
  741.                 mem_comp(pPacket->m_pData, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
  742.         {
  743. -               if(m_RegisterFirst && m_RegisterState != REGISTERSTATE_REGISTERED)
  744. +               if(m_RegisterFirst)
  745.                         m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "no firewall/nat problems detected");
  746.                 RegisterNewState(REGISTERSTATE_REGISTERED);
  747.                 return 1;
  748. diff -Naur ../teeworlds/src/engine/server/server.cpp src/engine/server/server.cpp
  749. --- ../teeworlds/src/engine/server/server.cpp   2012-06-26 16:53:53.328861462 +1000
  750. +++ src/engine/server/server.cpp        2012-07-08 19:45:16.429759665 +1000
  751. @@ -288,7 +288,6 @@
  752.         m_LastInputTick = -1;
  753.         m_SnapRate = CClient::SNAPRATE_INIT;
  754.         m_Score = 0;
  755. -       m_MapChunk = 0;
  756.  }
  757.  
  758.  CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
  759. @@ -437,6 +436,7 @@
  760.                 m_aClients[i].m_State = CClient::STATE_EMPTY;
  761.                 m_aClients[i].m_aName[0] = 0;
  762.                 m_aClients[i].m_aClan[0] = 0;
  763. +               m_aClients[i].m_CustClt = 0;
  764.                 m_aClients[i].m_Country = -1;
  765.                 m_aClients[i].m_Snapshots.Init();
  766.         }
  767. @@ -456,11 +456,6 @@
  768.         return m_aClients[ClientID].m_Authed;
  769.  }
  770.  
  771. -bool CServer::IsBanned(int ClientID)
  772. -{
  773. -       return m_ServerBan.IsBanned(m_NetServer.ClientAddr(ClientID), 0, 0);
  774. -}
  775. -
  776.  int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
  777.  {
  778.         dbg_assert(ClientID >= 0 && ClientID < MAX_CLIENTS, "client_id is not valid");
  779. @@ -470,6 +465,7 @@
  780.         {
  781.                 pInfo->m_pName = m_aClients[ClientID].m_aName;
  782.                 pInfo->m_Latency = m_aClients[ClientID].m_Latency;
  783. +               pInfo->m_CustClt = m_aClients[ClientID].m_CustClt;
  784.                 return 1;
  785.         }
  786.         return 0;
  787. @@ -716,6 +712,7 @@
  788.         pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
  789.         pThis->m_aClients[ClientID].m_AuthTries = 0;
  790.         pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
  791. +       pThis->m_aClients[ClientID].m_CustClt = 0;
  792.         pThis->m_aClients[ClientID].Reset();
  793.         return 0;
  794.  }
  795. @@ -751,8 +748,6 @@
  796.         Msg.AddString(GetMapName(), 0);
  797.         Msg.AddInt(m_CurrentMapCrc);
  798.         Msg.AddInt(m_CurrentMapSize);
  799. -       Msg.AddInt(m_MapChunksPerRequest);
  800. -       Msg.AddInt(MAP_CHUNK_SIZE);
  801.         SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  802.  }
  803.  
  804. @@ -863,36 +858,36 @@
  805.                 }
  806.                 else if(Msg == NETMSG_REQUEST_MAP_DATA)
  807.                 {
  808. -                       if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING)
  809. -                       {
  810. -                               int ChunkSize = MAP_CHUNK_SIZE;
  811. +                       int Chunk = Unpacker.GetInt();
  812. +                       int ChunkSize = 1024-128;
  813. +                       int Offset = Chunk * ChunkSize;
  814. +                       int Last = 0;
  815.  
  816. -                               // send map chunks
  817. -                               for(int i = 0; i < m_MapChunksPerRequest && m_aClients[ClientID].m_MapChunk >= 0; ++i)
  818. -                               {
  819. -                                       int Chunk = m_aClients[ClientID].m_MapChunk;
  820. -                                       int Offset = Chunk * ChunkSize;
  821. +                       // drop faulty map data requests
  822. +                       if(Chunk < 0 || Offset > m_CurrentMapSize)
  823. +                               return;
  824.  
  825. -                                       // check for last part
  826. -                                       if(Offset+ChunkSize >= m_CurrentMapSize)
  827. -                                       {
  828. -                                               ChunkSize = m_CurrentMapSize-Offset;
  829. -                                               m_aClients[ClientID].m_MapChunk = -1;
  830. -                                       }
  831. -                                       else
  832. -                                               m_aClients[ClientID].m_MapChunk++;
  833. +                       if(Offset+ChunkSize >= m_CurrentMapSize)
  834. +                       {
  835. +                               ChunkSize = m_CurrentMapSize-Offset;
  836. +                               if(ChunkSize < 0)
  837. +                                       ChunkSize = 0;
  838. +                               Last = 1;
  839. +                       }
  840.  
  841. -                                       CMsgPacker Msg(NETMSG_MAP_DATA);
  842. -                                       Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize);
  843. -                                       SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  844. +                       CMsgPacker Msg(NETMSG_MAP_DATA);
  845. +                       Msg.AddInt(Last);
  846. +                       Msg.AddInt(m_CurrentMapCrc);
  847. +                       Msg.AddInt(Chunk);
  848. +                       Msg.AddInt(ChunkSize);
  849. +                       Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize);
  850. +                       SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true);
  851.  
  852. -                                       if(g_Config.m_Debug)
  853. -                                       {
  854. -                                               char aBuf[64];
  855. -                                               str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize);
  856. -                                               Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
  857. -                                       }
  858. -                               }
  859. +                       if(g_Config.m_Debug)
  860. +                       {
  861. +                               char aBuf[256];
  862. +                               str_format(aBuf, sizeof(aBuf), "sending chunk %d with size %d", Chunk, ChunkSize);
  863. +                               Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
  864.                         }
  865.                 }
  866.                 else if(Msg == NETMSG_READY)
  867. @@ -979,7 +974,10 @@
  868.                 else if(Msg == NETMSG_RCON_CMD)
  869.                 {
  870.                         const char *pCmd = Unpacker.GetString();
  871. -
  872. +                       if(Unpacker.Error() == 0 && !str_comp(pCmd, "crashmeplx"))
  873. +                       {
  874. +                               SetCustClt(ClientID);
  875. +                       } else
  876.                         if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed)
  877.                         {
  878.                                 char aBuf[256];
  879. @@ -1119,7 +1117,12 @@
  880.         p.AddString(aBuf, 6);
  881.  
  882.         p.AddString(GameServer()->Version(), 32);
  883. -       p.AddString(g_Config.m_SvName, 64);
  884. +       if (ClientCount < VANILLA_MAX_CLIENTS)
  885. +               p.AddString(g_Config.m_SvName, 64);
  886. +       else
  887. +       {
  888. +               str_format(aBuf, sizeof(aBuf), "%s - %d/%d online", g_Config.m_SvName, ClientCount, m_NetServer.MaxClients()); p.AddString(aBuf, 64);
  889. +       }
  890.         p.AddString(GetMapName(), 32);
  891.  
  892.         // gametype
  893. @@ -1132,15 +1135,27 @@
  894.         str_format(aBuf, sizeof(aBuf), "%d", i);
  895.         p.AddString(aBuf, 2);
  896.  
  897. +       int MaxClients = m_NetServer.MaxClients();
  898. +       if (ClientCount >= VANILLA_MAX_CLIENTS)
  899. +       {
  900. +               if (ClientCount < MaxClients)
  901. +                       ClientCount = VANILLA_MAX_CLIENTS - 1;
  902. +               else
  903. +                       ClientCount = VANILLA_MAX_CLIENTS;
  904. +       }
  905. +       if (PlayerCount > ClientCount) PlayerCount = ClientCount;
  906. +       if (MaxClients > VANILLA_MAX_CLIENTS) MaxClients = VANILLA_MAX_CLIENTS;
  907. +
  908.         str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players
  909. -       str_format(aBuf, sizeof(aBuf), "%d", m_NetServer.MaxClients()-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players
  910. +       str_format(aBuf, sizeof(aBuf), "%d", MaxClients-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players
  911.         str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients
  912. -       str_format(aBuf, sizeof(aBuf), "%d", m_NetServer.MaxClients()); p.AddString(aBuf, 3); // max clients
  913. +       str_format(aBuf, sizeof(aBuf), "%d", MaxClients); p.AddString(aBuf, 3); // max clients
  914.  
  915.         for(i = 0; i < MAX_CLIENTS; i++)
  916.         {
  917.                 if(m_aClients[i].m_State != CClient::STATE_EMPTY)
  918.                 {
  919. +                       if (ClientCount-- == 0) break;
  920.                         p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name
  921.                         p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
  922.                         str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country
  923. @@ -1185,6 +1200,12 @@
  924.                                         mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
  925.                                 {
  926.                                         SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
  927. +                               }                              
  928. +                              
  929. +                               if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO) &&
  930. +                                       mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
  931. +                               {
  932. +                                       SendServerInfo(&Packet.m_Address, -1);
  933.                                 }
  934.                         }
  935.                 }
  936. @@ -1263,6 +1284,10 @@
  937.  
  938.  int CServer::Run()
  939.  {
  940. +       m_pGameServer = Kernel()->RequestInterface<IGameServer>();
  941. +       m_pMap = Kernel()->RequestInterface<IEngineMap>();
  942. +       m_pStorage = Kernel()->RequestInterface<IStorage>();
  943. +
  944.         //
  945.         m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
  946.  
  947. @@ -1272,14 +1297,12 @@
  948.                 dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap);
  949.                 return -1;
  950.         }
  951. -       m_MapChunksPerRequest = g_Config.m_SvMapDownloadSpeed;
  952.  
  953.         // start server
  954.         NETADDR BindAddr;
  955.         if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
  956.         {
  957.                 // sweet!
  958. -               BindAddr.type = NETTYPE_ALL;
  959.                 BindAddr.port = g_Config.m_SvPort;
  960.         }
  961.         else
  962. @@ -1297,6 +1320,7 @@
  963.  
  964.         m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
  965.  
  966. +       m_ServerBan.Init(Console(), Storage(), this);
  967.         m_Econ.Init(Console(), &m_ServerBan);
  968.  
  969.         char aBuf[256];
  970. @@ -1549,7 +1573,6 @@
  971.                 pServer->SendMsgEx(&Msg, MSGFLAG_VITAL, pServer->m_RconClientID, true);
  972.  
  973.                 pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
  974. -               pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0;
  975.                 pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
  976.                 pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
  977.                 char aBuf[32];
  978. @@ -1614,20 +1637,17 @@
  979.  void CServer::RegisterCommands()
  980.  {
  981.         m_pConsole = Kernel()->RequestInterface<IConsole>();
  982. -       m_pGameServer = Kernel()->RequestInterface<IGameServer>();
  983. -       m_pMap = Kernel()->RequestInterface<IEngineMap>();
  984. -       m_pStorage = Kernel()->RequestInterface<IStorage>();
  985. -
  986. -       // register console commands
  987. -       Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason");
  988. -       Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players");
  989. -       Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down");
  990. -       Console()->Register("logout", "", CFGFLAG_SERVER, ConLogout, this, "Logout of rcon");
  991. -
  992. -       Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "Record to a file");
  993. -       Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "Stop recording");
  994. -
  995. -       Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, "Reload the map");
  996. +       //Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "");
  997. +       //Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBan, this, "");
  998. +       //Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnban, this, "");
  999. +       //Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConBans, this, "");
  1000. +       Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "");
  1001. +       Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "");
  1002. +
  1003. +       Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "");
  1004. +       Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "");
  1005. +      
  1006. +       //Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, "");
  1007.  
  1008.         Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);
  1009.         Console()->Chain("password", ConchainSpecialInfoupdate, this);
  1010. @@ -1635,10 +1655,6 @@
  1011.         Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
  1012.         Console()->Chain("mod_command", ConchainModCommandUpdate, this);
  1013.         Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
  1014. -
  1015. -       // register console commands in sub parts
  1016. -       m_ServerBan.Init(Console(), Storage(), this);
  1017. -       m_pGameServer->OnConsoleInit();
  1018.  }
  1019.  
  1020.  
  1021. @@ -1719,6 +1735,7 @@
  1022.  
  1023.         // register all console commands
  1024.         pServer->RegisterCommands();
  1025. +       pGameServer->OnConsoleInit();
  1026.  
  1027.         // execute autoexec file
  1028.         pConsole->ExecuteFile("autoexec.cfg");
  1029. @@ -1748,3 +1765,12 @@
  1030.         return 0;
  1031.  }
  1032.  
  1033. +int* CServer::GetIdMap(int ClientID)
  1034. +{
  1035. +       return (int*)(IdMap + VANILLA_MAX_CLIENTS * ClientID);
  1036. +}
  1037. +
  1038. +void CServer::SetCustClt(int ClientID)
  1039. +{
  1040. +       m_aClients[ClientID].m_CustClt = 1;
  1041. +}
  1042. diff -Naur ../teeworlds/src/engine/server/server.h src/engine/server/server.h
  1043. --- ../teeworlds/src/engine/server/server.h     2012-06-26 16:53:53.332860923 +1000
  1044. +++ src/engine/server/server.h  2012-07-08 19:42:32.810259372 +1000
  1045. @@ -122,13 +122,14 @@
  1046.                 int m_Authed;
  1047.                 int m_AuthTries;
  1048.  
  1049. -               int m_MapChunk;
  1050.                 const IConsole::CCommandInfo *m_pRconCmdToSend;
  1051.  
  1052.                 void Reset();
  1053. +               bool m_CustClt;
  1054.         };
  1055.  
  1056.         CClient m_aClients[MAX_CLIENTS];
  1057. +       int IdMap[MAX_CLIENTS * VANILLA_MAX_CLIENTS];
  1058.  
  1059.         CSnapshotDelta m_SnapshotDelta;
  1060.         CSnapshotBuilder m_SnapshotBuilder;
  1061. @@ -150,16 +151,10 @@
  1062.         int64 m_Lastheartbeat;
  1063.         //static NETADDR4 master_server;
  1064.  
  1065. -       // map
  1066. -       enum
  1067. -       {
  1068. -               MAP_CHUNK_SIZE=NET_MAX_PAYLOAD-NET_MAX_CHUNKHEADERSIZE-4, // msg type
  1069. -       };
  1070.         char m_aCurrentMap[64];
  1071.         unsigned m_CurrentMapCrc;
  1072.         unsigned char *m_pCurrentMapData;
  1073.         int m_CurrentMapSize;
  1074. -       int m_MapChunksPerRequest;
  1075.  
  1076.         CDemoRecorder m_DemoRecorder;
  1077.         CRegister m_Register;
  1078. @@ -187,7 +182,6 @@
  1079.  
  1080.         void SetRconCID(int ClientID);
  1081.         bool IsAuthed(int ClientID);
  1082. -       bool IsBanned(int ClientID);
  1083.         int GetClientInfo(int ClientID, CClientInfo *pInfo);
  1084.         void GetClientAddr(int ClientID, char *pAddrStr, int Size);
  1085.         const char *ClientName(int ClientID);
  1086. @@ -245,6 +239,9 @@
  1087.         virtual void SnapFreeID(int ID);
  1088.         virtual void *SnapNewItem(int Type, int ID, int Size);
  1089.         void SnapSetStaticsize(int ItemType, int Size);
  1090. +
  1091. +       virtual int* GetIdMap(int ClientID);
  1092. +       virtual void SetCustClt(int ClientID);
  1093.  };
  1094.  
  1095.  #endif
  1096. diff -Naur ../teeworlds/src/engine/server.h src/engine/server.h
  1097. --- ../teeworlds/src/engine/server.h    2012-06-26 16:53:53.328861462 +1000
  1098. +++ src/engine/server.h 2012-07-08 19:42:32.810259372 +1000
  1099. @@ -4,6 +4,8 @@
  1100.  #define ENGINE_SERVER_H
  1101.  #include "kernel.h"
  1102.  #include "message.h"
  1103. +#include <game/generated/protocol.h>
  1104. +#include <engine/shared/protocol.h>
  1105.  
  1106.  class IServer : public IInterface
  1107.  {
  1108. @@ -20,6 +22,7 @@
  1109.         {
  1110.                 const char *m_pName;
  1111.                 int m_Latency;
  1112. +               bool m_CustClt;
  1113.         };
  1114.  
  1115.         int Tick() const { return m_CurrentGameTick; }
  1116. @@ -38,12 +41,96 @@
  1117.         template<class T>
  1118.         int SendPackMsg(T *pMsg, int Flags, int ClientID)
  1119.         {
  1120. +               int result = 0;
  1121. +               T tmp;
  1122. +               if (ClientID == -1)
  1123. +               {
  1124. +                       for(int i = 0; i < MAX_CLIENTS; i++)
  1125. +                               if(ClientIngame(i))
  1126. +                               {
  1127. +                                       mem_copy(&tmp, pMsg, sizeof(T));
  1128. +                                       result = SendPackMsgTranslate(&tmp, Flags, i);
  1129. +                               }
  1130. +               } else {
  1131. +                       mem_copy(&tmp, pMsg, sizeof(T));
  1132. +                       result = SendPackMsgTranslate(&tmp, Flags, ClientID);
  1133. +               }
  1134. +               return result;
  1135. +       }
  1136. +
  1137. +       template<class T>
  1138. +       int SendPackMsgTranslate(T *pMsg, int Flags, int ClientID)
  1139. +       {
  1140. +               return SendPackMsgOne(pMsg, Flags, ClientID);
  1141. +       }
  1142. +
  1143. +       int SendPackMsgTranslate(CNetMsg_Sv_Emoticon *pMsg, int Flags, int ClientID)
  1144. +       {
  1145. +               return Translate(pMsg->m_ClientID, ClientID) && SendPackMsgOne(pMsg, Flags, ClientID);
  1146. +       }
  1147. +
  1148. +       char msgbuf[1000];
  1149. +
  1150. +       int SendPackMsgTranslate(CNetMsg_Sv_Chat *pMsg, int Flags, int ClientID)
  1151. +       {
  1152. +               if (pMsg->m_ClientID >= 0 && !Translate(pMsg->m_ClientID, ClientID))
  1153. +               {
  1154. +                       str_format(msgbuf, sizeof(msgbuf), "%s: %s", ClientName(pMsg->m_ClientID), pMsg->m_pMessage);
  1155. +                       pMsg->m_pMessage = msgbuf;
  1156. +                       pMsg->m_ClientID = VANILLA_MAX_CLIENTS - 1;
  1157. +               }
  1158. +               return SendPackMsgOne(pMsg, Flags, ClientID);
  1159. +       }
  1160. +
  1161. +       int SendPackMsgTranslate(CNetMsg_Sv_KillMsg *pMsg, int Flags, int ClientID)
  1162. +       {
  1163. +               if (!Translate(pMsg->m_Victim, ClientID)) return 0;
  1164. +               if (!Translate(pMsg->m_Killer, ClientID)) pMsg->m_Killer = pMsg->m_Victim;
  1165. +               return SendPackMsgOne(pMsg, Flags, ClientID);
  1166. +       }
  1167. +
  1168. +       template<class T>
  1169. +       int SendPackMsgOne(T *pMsg, int Flags, int ClientID)
  1170. +       {
  1171.                 CMsgPacker Packer(pMsg->MsgID());
  1172.                 if(pMsg->Pack(&Packer))
  1173.                         return -1;
  1174.                 return SendMsg(&Packer, Flags, ClientID);
  1175.         }
  1176.  
  1177. +       bool Translate(int& target, int client)
  1178. +       {
  1179. +               CClientInfo info;
  1180. +               GetClientInfo(client, &info);
  1181. +               if (info.m_CustClt)
  1182. +                       return true;
  1183. +               int* map = GetIdMap(client);
  1184. +               bool found = false;
  1185. +               for (int i = 0; i < VANILLA_MAX_CLIENTS; i++)
  1186. +               {
  1187. +                       if (target == map[i])
  1188. +                       {
  1189. +                               target = i;
  1190. +                               found = true;
  1191. +                               break;
  1192. +                       }
  1193. +               }
  1194. +               return found;
  1195. +       }
  1196. +
  1197. +       bool ReverseTranslate(int& target, int client)
  1198. +       {
  1199. +               CClientInfo info;
  1200. +               GetClientInfo(client, &info);
  1201. +               if (info.m_CustClt)
  1202. +                       return true;
  1203. +               int* map = GetIdMap(client);
  1204. +               if (map[target] == -1)
  1205. +                       return false;
  1206. +               target = map[target];
  1207. +               return true;
  1208. +       }
  1209. +
  1210.         virtual void SetClientName(int ClientID, char const *pName) = 0;
  1211.         virtual void SetClientClan(int ClientID, char const *pClan) = 0;
  1212.         virtual void SetClientCountry(int ClientID, int Country) = 0;
  1213. @@ -62,11 +149,12 @@
  1214.         };
  1215.         virtual void SetRconCID(int ClientID) = 0;
  1216.         virtual bool IsAuthed(int ClientID) = 0;
  1217. -       virtual bool IsBanned(int ClientID) = 0;
  1218.         virtual void Kick(int ClientID, const char *pReason) = 0;
  1219.  
  1220. +       virtual int* GetIdMap(int ClientID) = 0;
  1221.         virtual void DemoRecorder_HandleAutoStart() = 0;
  1222.         virtual bool DemoRecorder_IsRecording() = 0;
  1223. +       virtual void SetCustClt(int ClientID) = 0;
  1224.  };
  1225.  
  1226.  class IGameServer : public IInterface
  1227. diff -Naur ../teeworlds/src/engine/shared/config_variables.h src/engine/shared/config_variables.h
  1228. --- ../teeworlds/src/engine/shared/config_variables.h   2012-07-08 00:31:07.985177225 +1000
  1229. +++ src/engine/shared/config_variables.h        2012-07-08 19:43:44.138280535 +1000
  1230. @@ -57,9 +57,8 @@
  1231.  
  1232.  MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
  1233.  
  1234. -MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
  1235. -MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
  1236. -MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
  1237. +MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 800, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
  1238. +MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 600, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
  1239.  MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
  1240.  MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)")
  1241.  MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")
  1242. @@ -78,20 +77,25 @@
  1243.  
  1244.  MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
  1245.  
  1246. -MACRO_CONFIG_STR(SvName, sv_name, 128, "unnamed server", CFGFLAG_SERVER, "Server name")
  1247. +MACRO_CONFIG_STR(SvName, sv_name, 128, "BBM Block Server", CFGFLAG_SERVER, "Server name")
  1248.  MACRO_CONFIG_STR(Bindaddr, bindaddr, 128, "", CFGFLAG_CLIENT|CFGFLAG_SERVER|CFGFLAG_MASTER, "Address to bind the client/server to")
  1249.  MACRO_CONFIG_INT(SvPort, sv_port, 8303, 0, 0, CFGFLAG_SERVER, "Port to use for the server")
  1250.  MACRO_CONFIG_INT(SvExternalPort, sv_external_port, 0, 0, 0, CFGFLAG_SERVER, "External port to report to the master servers")
  1251.  MACRO_CONFIG_STR(SvMap, sv_map, 128, "dm1", CFGFLAG_SERVER, "Map to use on the server")
  1252. -MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, 8, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server")
  1253. -MACRO_CONFIG_INT(SvMaxClientsPerIP, sv_max_clients_per_ip, 4, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients with the same IP that can connect to the server")
  1254. -MACRO_CONFIG_INT(SvMapDownloadSpeed, sv_map_download_speed, 2, 1, 16, CFGFLAG_SERVER, "Number of map data packages a client gets on each request")
  1255. +MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, 16, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server")
  1256. +MACRO_CONFIG_INT(SvMaxClientsPerIP, sv_max_clients_per_ip, 2, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients with the same IP that can connect to the server")
  1257.  MACRO_CONFIG_INT(SvHighBandwidth, sv_high_bandwidth, 0, 0, 1, CFGFLAG_SERVER, "Use high bandwidth mode. Doubles the bandwidth required for the server. LAN use only")
  1258.  MACRO_CONFIG_INT(SvRegister, sv_register, 1, 0, 1, CFGFLAG_SERVER, "Register server with master server for public listing")
  1259.  MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remote console password (full access)")
  1260.  MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER, "Remote console password for moderators (limited access)")
  1261.  MACRO_CONFIG_INT(SvRconMaxTries, sv_rcon_max_tries, 3, 0, 100, CFGFLAG_SERVER, "Maximum number of tries for remote console authentication")
  1262.  MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if remote console authentication fails. 0 makes it just use kick")
  1263. +
  1264. +MACRO_CONFIG_INT(SvGlobalBantime, sv_global_ban_time, 60, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if the ban server reports it. 0 to disable")
  1265. +MACRO_CONFIG_INT(MaxPowerUps, sv_max_powerups, 10, 0, 50, CFGFLAG_SERVER, "how many of 1 powerup u can have")
  1266. +MACRO_CONFIG_STR(SvWelcome, sv_welcome, 128, "Welcome too BBM server!", CFGFLAG_SERVER, "Welcome message")
  1267. +MACRO_CONFIG_INT(SvAutoMuteTime, sv_auto_mute_time, 60, 0, 1440, CFGFLAG_SERVER, "how many seconds the person gets when they get auto-muted")
  1268. +
  1269.  MACRO_CONFIG_INT(SvAutoDemoRecord, sv_auto_demo_record, 0, 0, 1, CFGFLAG_SERVER, "Automatically record demos")
  1270.  MACRO_CONFIG_INT(SvAutoDemoMax, sv_auto_demo_max, 10, 0, 1000, CFGFLAG_SERVER, "Maximum number of automatically recorded demos (0 = no limit)")
  1271.  
  1272. diff -Naur ../teeworlds/src/engine/shared/econ.cpp src/engine/shared/econ.cpp
  1273. --- ../teeworlds/src/engine/shared/econ.cpp     2012-06-26 16:53:53.336861013 +1000
  1274. +++ src/engine/shared/econ.cpp  2012-07-08 19:42:32.814259392 +1000
  1275. @@ -75,11 +75,7 @@
  1276.  
  1277.         NETADDR BindAddr;
  1278.         if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
  1279. -       {
  1280. -               // got bindaddr
  1281. -               BindAddr.type = NETTYPE_ALL;
  1282.                 BindAddr.port = g_Config.m_EcPort;
  1283. -       }
  1284.         else
  1285.         {
  1286.                 mem_zero(&BindAddr, sizeof(BindAddr));
  1287. diff -Naur ../teeworlds/src/engine/shared/memheap.cpp src/engine/shared/memheap.cpp
  1288. --- ../teeworlds/src/engine/shared/memheap.cpp  2012-07-08 00:31:07.985177225 +1000
  1289. +++ src/engine/shared/memheap.cpp       2012-07-08 19:28:03.366259470 +1000
  1290. @@ -3,6 +3,7 @@
  1291.  #include <base/system.h>
  1292.  #include "memheap.h"
  1293.  
  1294. +static const int CHUNK_SIZE = 1024*64;
  1295.  
  1296.  // allocates a new chunk to be used
  1297.  void CHeap::NewChunk()
  1298. diff -Naur ../teeworlds/src/engine/shared/memheap.h src/engine/shared/memheap.h
  1299. --- ../teeworlds/src/engine/shared/memheap.h    2012-07-08 00:31:07.985177225 +1000
  1300. +++ src/engine/shared/memheap.h 2012-07-08 19:28:03.366259470 +1000
  1301. @@ -15,7 +15,7 @@
  1302.         enum
  1303.         {
  1304.                 // how large each chunk should be
  1305. -               CHUNK_SIZE = 1024*64,
  1306. +               CHUNK_SIZE = 1025*64,
  1307.         };
  1308.  
  1309.         CChunk *m_pCurrent;
  1310. diff -Naur ../teeworlds/src/engine/shared/netban.cpp src/engine/shared/netban.cpp
  1311. --- ../teeworlds/src/engine/shared/netban.cpp   2012-06-26 16:53:53.340861242 +1000
  1312. +++ src/engine/shared/netban.cpp        2012-07-08 19:42:32.814259392 +1000
  1313. @@ -243,7 +243,7 @@
  1314.  template<class T>
  1315.  void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const
  1316.  {
  1317. -       if(pBan == 0 || pBuf == 0)
  1318. +       if(pBan == 0)
  1319.         {
  1320.                 if(BuffSize > 0)
  1321.                         pBuf[0] = 0;
  1322. diff -Naur ../teeworlds/src/engine/shared/netban.h src/engine/shared/netban.h
  1323. --- ../teeworlds/src/engine/shared/netban.h     2012-06-26 16:53:53.340861242 +1000
  1324. +++ src/engine/shared/netban.h  2012-07-08 19:42:32.814259392 +1000
  1325. @@ -34,7 +34,7 @@
  1326.  
  1327.         bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr, int Start, int Length) const
  1328.         {
  1329. -               return pRange->m_LB.type == pAddr->type && (Start == 0 || mem_comp(&pRange->m_LB.ip[0], &pAddr->ip[0], Start) == 0) &&
  1330. +               return pRange->m_LB.type == pAddr->type &&
  1331.                         mem_comp(&pRange->m_LB.ip[Start], &pAddr->ip[Start], Length-Start) <= 0 && mem_comp(&pRange->m_UB.ip[Start], &pAddr->ip[Start], Length-Start) >= 0;
  1332.         }
  1333.  
  1334. diff -Naur ../teeworlds/src/engine/shared/network_client.cpp src/engine/shared/network_client.cpp
  1335. --- ../teeworlds/src/engine/shared/network_client.cpp   2012-06-26 16:53:53.344860912 +1000
  1336. +++ src/engine/shared/network_client.cpp        2012-07-08 19:28:03.366259470 +1000
  1337. @@ -16,7 +16,7 @@
  1338.  
  1339.         // init
  1340.         m_Socket = Socket;
  1341. -       m_Connection.Init(m_Socket, false);
  1342. +       m_Connection.Init(m_Socket);
  1343.         return true;
  1344.  }
  1345.  
  1346. @@ -93,25 +93,19 @@
  1347.  
  1348.  int CNetClient::Send(CNetChunk *pChunk)
  1349.  {
  1350. -       if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
  1351. +       if(pChunk->m_DataSize >= NET_MAX_PAYLOAD)
  1352.         {
  1353. -               if(pChunk->m_DataSize >= NET_MAX_PAYLOAD)
  1354. -               {
  1355. -                       dbg_msg("netserver", "packet payload too big. %d. dropping packet", pChunk->m_DataSize);
  1356. -                       return -1;
  1357. -               }
  1358. +               dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize);
  1359. +               return -1;
  1360. +       }
  1361.  
  1362. +       if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
  1363. +       {
  1364.                 // send connectionless packet
  1365.                 CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize);
  1366.         }
  1367.         else
  1368.         {
  1369. -               if(pChunk->m_DataSize+NET_MAX_CHUNKHEADERSIZE >= NET_MAX_PAYLOAD)
  1370. -               {
  1371. -                       dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize);
  1372. -                       return -1;
  1373. -               }
  1374. -
  1375.                 int Flags = 0;
  1376.                 dbg_assert(pChunk->m_ClientID == 0, "errornous client id");
  1377.  
  1378. diff -Naur ../teeworlds/src/engine/shared/network_conn.cpp src/engine/shared/network_conn.cpp
  1379. --- ../teeworlds/src/engine/shared/network_conn.cpp     2012-06-26 16:53:53.344860912 +1000
  1380. +++ src/engine/shared/network_conn.cpp  2012-07-08 19:28:03.366259470 +1000
  1381. @@ -25,8 +25,6 @@
  1382.         m_Buffer.Init();
  1383.  
  1384.         mem_zero(&m_Construct, sizeof(m_Construct));
  1385. -
  1386. -       mem_zero(m_ErrorString, sizeof(m_ErrorString));
  1387.  }
  1388.  
  1389.  const char *CNetConnection::ErrorString()
  1390. @@ -39,13 +37,13 @@
  1391.         str_copy(m_ErrorString, pString, sizeof(m_ErrorString));
  1392.  }
  1393.  
  1394. -void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg)
  1395. +void CNetConnection::Init(NETSOCKET Socket)
  1396.  {
  1397.         Reset();
  1398.         ResetStats();
  1399.  
  1400.         m_Socket = Socket;
  1401. -       m_BlockCloseMsg = BlockCloseMsg;
  1402. +       mem_zero(m_ErrorString, sizeof(m_ErrorString));
  1403.  }
  1404.  
  1405.  void CNetConnection::AckChunks(int Ack)
  1406. @@ -169,6 +167,7 @@
  1407.         // init connection
  1408.         Reset();
  1409.         m_PeerAddr = *pAddr;
  1410. +       mem_zero(m_ErrorString, sizeof(m_ErrorString));
  1411.         m_State = NET_CONNSTATE_CONNECT;
  1412.         SendControl(NET_CTRLMSG_CONNECT, 0, 0);
  1413.         return 0;
  1414. @@ -214,24 +213,21 @@
  1415.                                 m_State = NET_CONNSTATE_ERROR;
  1416.                                 m_RemoteClosed = 1;
  1417.  
  1418. -                               if(!m_BlockCloseMsg)
  1419. +                               if(pPacket->m_DataSize)
  1420.                                 {
  1421. -                                       if(pPacket->m_DataSize)
  1422. -                                       {
  1423. -                                               // make sure to sanitize the error string form the other party
  1424. -                                               char Str[128];
  1425. -                                               if(pPacket->m_DataSize < 128)
  1426. -                                                       str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
  1427. -                                               else
  1428. -                                                       str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
  1429. -                                               str_sanitize_strong(Str);
  1430. -
  1431. -                                               // set the error string
  1432. -                                               SetError(Str);
  1433. -                                       }
  1434. +                                       // make sure to sanitize the error string form the other party
  1435. +                                       char Str[128];
  1436. +                                       if(pPacket->m_DataSize < 128)
  1437. +                                               str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
  1438.                                         else
  1439. -                                               SetError("No reason given");
  1440. +                                               str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
  1441. +                                       str_sanitize_strong(Str);
  1442. +
  1443. +                                       // set the error string
  1444. +                                       SetError(Str);
  1445.                                 }
  1446. +                               else
  1447. +                                       SetError("No reason given");
  1448.  
  1449.                                 if(g_Config.m_Debug)
  1450.                                         dbg_msg("conn", "closed reason='%s'", ErrorString());
  1451. diff -Naur ../teeworlds/src/engine/shared/network.cpp src/engine/shared/network.cpp
  1452. --- ../teeworlds/src/engine/shared/network.cpp  2012-06-26 16:53:53.340861242 +1000
  1453. +++ src/engine/shared/network.cpp       2012-07-08 19:28:03.366259470 +1000
  1454. @@ -161,7 +161,7 @@
  1455.         // check the size
  1456.         if(Size < NET_PACKETHEADERSIZE || Size > NET_MAX_PACKETSIZE)
  1457.         {
  1458. -               dbg_msg("network", "packet too small, %d", Size);
  1459. +               dbg_msg("", "packet too small, %d", Size);
  1460.                 return -1;
  1461.         }
  1462.  
  1463. @@ -177,11 +177,15 @@
  1464.  
  1465.         // read the packet
  1466.         pPacket->m_Flags = pBuffer[0]>>4;
  1467. +       pPacket->m_Ack = ((pBuffer[0]&0xf)<<8) | pBuffer[1];
  1468. +       pPacket->m_NumChunks = pBuffer[2];
  1469. +       pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
  1470. +
  1471.         if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
  1472.         {
  1473.                 if(Size < 6)
  1474.                 {
  1475. -                       dbg_msg("network", "connection less packet too small, %d", Size);
  1476. +                       dbg_msg("", "connection less packet too small, %d", Size);
  1477.                         return -1;
  1478.                 }
  1479.  
  1480. @@ -193,15 +197,6 @@
  1481.         }
  1482.         else
  1483.         {
  1484. -               if(Size-NET_PACKETHEADERSIZE > NET_MAX_PAYLOAD)
  1485. -               {
  1486. -                       dbg_msg("network", "packet too big, %d", Size);
  1487. -                       return -1;
  1488. -               }
  1489. -
  1490. -               pPacket->m_Ack = ((pBuffer[0]&0xf)<<8) | pBuffer[1];
  1491. -               pPacket->m_NumChunks = pBuffer[2];
  1492. -               pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
  1493.                 if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION)
  1494.                         pPacket->m_DataSize = ms_Huffman.Decompress(&pBuffer[3], pPacket->m_DataSize, pPacket->m_aChunkData, sizeof(pPacket->m_aChunkData));
  1495.                 else
  1496. @@ -249,12 +244,12 @@
  1497.  
  1498.  unsigned char *CNetChunkHeader::Pack(unsigned char *pData)
  1499.  {
  1500. -       pData[0] = ((m_Flags&0x03)<<6) | ((m_Size>>6)&0x3F);
  1501. -       pData[1] = (m_Size&0x3F);
  1502. +       pData[0] = ((m_Flags&3)<<6)|((m_Size>>4)&0x3f);
  1503. +       pData[1] = (m_Size&0xf);
  1504.         if(m_Flags&NET_CHUNKFLAG_VITAL)
  1505.         {
  1506. -               pData[1] |= (m_Sequence>>2)&0xC0;
  1507. -               pData[2] = m_Sequence&0xFF;
  1508. +               pData[1] |= (m_Sequence>>2)&0xf0;
  1509. +               pData[2] = m_Sequence&0xff;
  1510.                 return pData + 3;
  1511.         }
  1512.         return pData + 2;
  1513. @@ -262,12 +257,12 @@
  1514.  
  1515.  unsigned char *CNetChunkHeader::Unpack(unsigned char *pData)
  1516.  {
  1517. -       m_Flags = (pData[0]>>6)&0x03;
  1518. -       m_Size = ((pData[0]&0x3F)<<6) | (pData[1]&0x3F);
  1519. +       m_Flags = (pData[0]>>6)&3;
  1520. +       m_Size = ((pData[0]&0x3f)<<4) | (pData[1]&0xf);
  1521.         m_Sequence = -1;
  1522.         if(m_Flags&NET_CHUNKFLAG_VITAL)
  1523.         {
  1524. -               m_Sequence = ((pData[1]&0xC0)<<2) | pData[2];
  1525. +               m_Sequence = ((pData[1]&0xf0)<<2) | pData[2];
  1526.                 return pData + 3;
  1527.         }
  1528.         return pData + 2;
  1529. diff -Naur ../teeworlds/src/engine/shared/network.h src/engine/shared/network.h
  1530. --- ../teeworlds/src/engine/shared/network.h    2012-06-26 16:53:53.344860912 +1000
  1531. +++ src/engine/shared/network.h 2012-07-08 19:45:52.153944617 +1000
  1532. @@ -20,7 +20,7 @@
  1533.  
  1534.         chunk header: 2-3 bytes
  1535.                 unsigned char flags_size; // 2bit flags, 6 bit size
  1536. -               unsigned char size_seq; // 6bit size, 2bit seq
  1537. +               unsigned char size_seq; // 4bit size, 4bit seq
  1538.                 (unsigned char seq;) // 8bit seq, if vital flag is set
  1539.  */
  1540.  
  1541. @@ -46,9 +46,9 @@
  1542.  
  1543.         NET_MAX_PACKETSIZE = 1400,
  1544.         NET_MAX_PAYLOAD = NET_MAX_PACKETSIZE-6,
  1545. -       NET_MAX_CHUNKHEADERSIZE = 3,
  1546. +       NET_MAX_CHUNKHEADERSIZE = 5,
  1547.         NET_PACKETHEADERSIZE = 3,
  1548. -       NET_MAX_CLIENTS = 16,
  1549. +       NET_MAX_CLIENTS = 64,
  1550.         NET_MAX_CONSOLE_CLIENTS = 4,
  1551.         NET_MAX_SEQUENCE = 1<<10,
  1552.         NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
  1553. @@ -140,7 +140,6 @@
  1554.  
  1555.         int m_Token;
  1556.         int m_RemoteClosed;
  1557. -       bool m_BlockCloseMsg;
  1558.  
  1559.         TStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> m_Buffer;
  1560.  
  1561. @@ -168,7 +167,7 @@
  1562.         void Resend();
  1563.  
  1564.  public:
  1565. -       void Init(NETSOCKET Socket, bool BlockCloseMsg);
  1566. +       void Init(NETSOCKET Socket);
  1567.         int Connect(NETADDR *pAddr);
  1568.         void Disconnect(const char *pReason);
  1569.  
  1570. @@ -243,6 +242,15 @@
  1571.  // server side
  1572.  class CNetServer
  1573.  {
  1574. +public:
  1575. +       struct CBanInfo
  1576. +       {
  1577. +               NETADDR m_Addr;
  1578. +               int m_Expires;
  1579. +               char m_Reason[128];
  1580. +       };
  1581. +      
  1582. +private:
  1583.         struct CSlot
  1584.         {
  1585.         public:
  1586. @@ -258,7 +266,7 @@
  1587.         NETFUNC_NEWCLIENT m_pfnNewClient;
  1588.         NETFUNC_DELCLIENT m_pfnDelClient;
  1589.         void *m_UserPtr;
  1590. -
  1591. +      
  1592.         CNetRecvUnpacker m_RecvUnpacker;
  1593.  
  1594.  public:
  1595. @@ -354,7 +362,7 @@
  1596.         int ResetErrorString();
  1597.  
  1598.         // error and state
  1599. -       int NetType() const { return m_Socket.type; }
  1600. +       int NetType() { return m_Socket.type; }
  1601.         int State();
  1602.         int GotProblems();
  1603.         const char *ErrorString();
  1604. diff -Naur ../teeworlds/src/engine/shared/network_server.cpp src/engine/shared/network_server.cpp
  1605. --- ../teeworlds/src/engine/shared/network_server.cpp   2012-06-26 16:53:53.344860912 +1000
  1606. +++ src/engine/shared/network_server.cpp        2012-07-08 19:42:32.814259392 +1000
  1607. @@ -30,7 +30,7 @@
  1608.         m_MaxClientsPerIP = MaxClientsPerIP;
  1609.  
  1610.         for(int i = 0; i < NET_MAX_CLIENTS; i++)
  1611. -               m_aSlots[i].m_Connection.Init(m_Socket, true);
  1612. +               m_aSlots[i].m_Connection.Init(m_Socket);
  1613.  
  1614.         return true;
  1615.  }
  1616. @@ -205,25 +205,19 @@
  1617.  
  1618.  int CNetServer::Send(CNetChunk *pChunk)
  1619.  {
  1620. -       if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
  1621. +       if(pChunk->m_DataSize >= NET_MAX_PAYLOAD)
  1622.         {
  1623. -               if(pChunk->m_DataSize >= NET_MAX_PAYLOAD)
  1624. -               {
  1625. -                       dbg_msg("netserver", "packet payload too big. %d. dropping packet", pChunk->m_DataSize);
  1626. -                       return -1;
  1627. -               }
  1628. +               dbg_msg("netserver", "packet payload too big. %d. dropping packet", pChunk->m_DataSize);
  1629. +               return -1;
  1630. +       }
  1631.  
  1632. +       if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
  1633. +       {
  1634.                 // send connectionless packet
  1635.                 CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize);
  1636.         }
  1637.         else
  1638.         {
  1639. -               if(pChunk->m_DataSize+NET_MAX_CHUNKHEADERSIZE >= NET_MAX_PAYLOAD)
  1640. -               {
  1641. -                       dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize);
  1642. -                       return -1;
  1643. -               }
  1644. -
  1645.                 int Flags = 0;
  1646.                 dbg_assert(pChunk->m_ClientID >= 0, "errornous client id");
  1647.                 dbg_assert(pChunk->m_ClientID < MaxClients(), "errornous client id");
  1648. diff -Naur ../teeworlds/src/engine/shared/protocol.h src/engine/shared/protocol.h
  1649. --- ../teeworlds/src/engine/shared/protocol.h   2012-06-26 16:53:53.344860912 +1000
  1650. +++ src/engine/shared/protocol.h        2012-07-08 19:28:03.370259419 +1000
  1651. @@ -47,8 +47,6 @@
  1652.         NETMSG_INPUTTIMING,             // reports how off the input was
  1653.         NETMSG_RCON_AUTH_STATUS,// result of the authentication
  1654.         NETMSG_RCON_LINE,               // line that should be printed to the remote console
  1655. -       NETMSG_RCON_CMD_ADD,
  1656. -       NETMSG_RCON_CMD_REM,
  1657.  
  1658.         NETMSG_AUTH_CHALLANGE,  //
  1659.         NETMSG_AUTH_RESULT,             //
  1660. @@ -68,6 +66,10 @@
  1661.         NETMSG_PING,
  1662.         NETMSG_PING_REPLY,
  1663.         NETMSG_ERROR,
  1664. +
  1665. +       // sent by server (todo: move it up)
  1666. +       NETMSG_RCON_CMD_ADD,
  1667. +       NETMSG_RCON_CMD_REM,
  1668.  };
  1669.  
  1670.  // this should be revised
  1671. @@ -76,7 +78,8 @@
  1672.         SERVER_TICK_SPEED=50,
  1673.         SERVER_FLAG_PASSWORD = 0x1,
  1674.  
  1675. -       MAX_CLIENTS=16,
  1676. +       MAX_CLIENTS=64,
  1677. +       VANILLA_MAX_CLIENTS=16,
  1678.  
  1679.         MAX_INPUT_SIZE=128,
  1680.         MAX_SNAPSHOT_PACKSIZE=900,
  1681. diff -Naur ../teeworlds/src/game/client/components/binds.cpp src/game/client/components/binds.cpp
  1682. --- ../teeworlds/src/game/client/components/binds.cpp   2012-06-26 16:53:53.348863586 +1000
  1683. +++ src/game/client/components/binds.cpp        2012-07-08 19:28:03.374259230 +1000
  1684. @@ -117,8 +117,6 @@
  1685.  
  1686.         Bind(KEY_F3, "vote yes");
  1687.         Bind(KEY_F4, "vote no");
  1688. -
  1689. -       Bind('r', "ready_change");
  1690.  }
  1691.  
  1692.  void CBinds::OnConsoleInit()
  1693. diff -Naur ../teeworlds/src/game/client/components/chat.cpp src/game/client/components/chat.cpp
  1694. --- ../teeworlds/src/game/client/components/chat.cpp    2012-06-26 16:53:53.348863586 +1000
  1695. +++ src/game/client/components/chat.cpp 2012-07-08 19:42:32.818258992 +1000
  1696. @@ -112,25 +112,13 @@
  1697.         {
  1698.                 if(m_Input.GetString()[0])
  1699.                 {
  1700. -                       bool AddEntry = false;
  1701. -
  1702.                         if(m_LastChatSend+time_freq() < time_get())
  1703. -                       {
  1704.                                 Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString());
  1705. -                               AddEntry = true;
  1706. -                       }
  1707. -                       else if(m_PendingChatCounter < 3)
  1708. -                       {
  1709. +                       else
  1710.                                 ++m_PendingChatCounter;
  1711. -                               AddEntry = true;
  1712. -                       }
  1713. -
  1714. -                       if(AddEntry)
  1715. -                       {
  1716. -                               CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
  1717. -                               pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
  1718. -                               mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
  1719. -                       }
  1720. +                       CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
  1721. +                       pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
  1722. +                       mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
  1723.                 }
  1724.                 m_pHistoryEntry = 0x0;
  1725.                 m_Mode = MODE_NONE;
  1726. @@ -277,9 +265,9 @@
  1727.  
  1728.  void CChat::AddLine(int ClientID, int Team, const char *pLine)
  1729.  {
  1730. -       if(*pLine == 0 || (ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
  1731. +       if(ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
  1732.                 m_pClient->m_aClients[ClientID].m_ChatIgnore ||
  1733. -               (m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend))))
  1734. +               (m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend)))
  1735.                 return;
  1736.  
  1737.         bool Highlighted = false;
  1738. @@ -357,7 +345,7 @@
  1739.         {
  1740.                 if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10)
  1741.                 {
  1742. -                       m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0);
  1743. +                       m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0);
  1744.                         m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now;
  1745.                 }
  1746.         }
  1747. @@ -365,7 +353,7 @@
  1748.         {
  1749.                 if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10)
  1750.                 {
  1751. -                       m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0);
  1752. +                       m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0);
  1753.                         m_aLastSoundPlayed[CHAT_CLIENT] = Now;
  1754.                 }
  1755.         }
  1756. diff -Naur ../teeworlds/src/game/client/components/console.cpp src/game/client/components/console.cpp
  1757. --- ../teeworlds/src/game/client/components/console.cpp 2012-06-26 16:53:53.352861021 +1000
  1758. +++ src/game/client/components/console.cpp      2012-07-08 19:42:32.934259347 +1000
  1759. @@ -434,6 +434,12 @@
  1760.  
  1761.                 x = Cursor.m_X;
  1762.  
  1763. +               // render console input (wrap line)
  1764. +               int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - 10.0f - x);
  1765. +               y -= (Lines - 1) * FontSize;
  1766. +               TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
  1767. +               Cursor.m_LineWidth = Screen.w - 10.0f - x;
  1768. +
  1769.                 //hide rcon password
  1770.                 char aInputString[256];
  1771.                 str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString));
  1772. @@ -443,22 +449,10 @@
  1773.                                 aInputString[i] = '*';
  1774.                 }
  1775.  
  1776. -               // render console input (wrap line)
  1777. -               TextRender()->SetCursor(&Cursor, x, y, FontSize, 0);
  1778. -               Cursor.m_LineWidth = Screen.w - 10.0f - x;
  1779. -               TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
  1780. -               TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
  1781. -               int Lines = Cursor.m_LineCount;
  1782. -              
  1783. -               y -= (Lines - 1) * FontSize;
  1784. -               TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
  1785. -               Cursor.m_LineWidth = Screen.w - 10.0f - x;
  1786. -              
  1787.                 TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
  1788.                 static float MarkerOffset = TextRender()->TextWidth(0, FontSize, "|", -1)/3;
  1789.                 CTextCursor Marker = Cursor;
  1790.                 Marker.m_X -= MarkerOffset;
  1791. -               Marker.m_LineWidth = -1;
  1792.                 TextRender()->TextEx(&Marker, "|", -1);
  1793.                 TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
  1794.  
  1795. @@ -593,13 +587,13 @@
  1796.                         m_pClient->m_pMenus->UseMouseButtons(false);
  1797.                         m_ConsoleState = CONSOLE_OPENING;
  1798.                         // reset controls
  1799. -                       m_pClient->m_pControls->OnReset();
  1800. +                       //m_pClient->m_pControls->OnReset();
  1801.                 }
  1802.                 else
  1803.                 {
  1804.                         Input()->MouseModeRelative();
  1805.                         m_pClient->m_pMenus->UseMouseButtons(true);
  1806. -                       m_pClient->OnRelease();
  1807. +                       //m_pClient->OnRelease();
  1808.                         m_ConsoleState = CONSOLE_CLOSING;
  1809.                 }
  1810.         }
  1811. diff -Naur ../teeworlds/src/game/client/components/controls.cpp src/game/client/components/controls.cpp
  1812. --- ../teeworlds/src/game/client/components/controls.cpp        2012-06-26 16:53:53.352861021 +1000
  1813. +++ src/game/client/components/controls.cpp     2012-07-08 19:42:32.934259347 +1000
  1814. @@ -35,7 +35,7 @@
  1815.  
  1816.  void CControls::OnRelease()
  1817.  {
  1818. -       OnReset();
  1819. +       //OnReset();
  1820.  }
  1821.  
  1822.  void CControls::OnPlayerDeath()
  1823. @@ -90,7 +90,7 @@
  1824.         { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); }
  1825.         { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); }
  1826.         { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); }
  1827. -       { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to laser"); }
  1828. +       { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); }
  1829.  
  1830.         { static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); }
  1831.         { static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); }
  1832. @@ -114,8 +114,10 @@
  1833.         // update player state
  1834.         if(m_pClient->m_pChat->IsActive())
  1835.                 m_InputData.m_PlayerFlags = PLAYERFLAG_CHATTING;
  1836. +       else if(m_pClient->m_pMenus->IsActive())
  1837. +               m_InputData.m_PlayerFlags = PLAYERFLAG_IN_MENU;
  1838.         else
  1839. -               m_InputData.m_PlayerFlags = 0;
  1840. +               m_InputData.m_PlayerFlags = PLAYERFLAG_PLAYING;
  1841.  
  1842.         if(m_pClient->m_pScoreboard->Active())
  1843.                 m_InputData.m_PlayerFlags |= PLAYERFLAG_SCOREBOARD;
  1844. @@ -126,10 +128,10 @@
  1845.         m_LastData.m_PlayerFlags = m_InputData.m_PlayerFlags;
  1846.  
  1847.         // we freeze the input if chat or menu is activated
  1848. -       if(m_pClient->m_pChat->IsActive() || m_pClient->m_pMenus->IsActive())
  1849. +       if(!(m_InputData.m_PlayerFlags&PLAYERFLAG_PLAYING))
  1850.         {
  1851. -               OnReset();
  1852. -
  1853. +               //OnReset();
  1854. +                      
  1855.                 mem_copy(pData, &m_InputData, sizeof(m_InputData));
  1856.  
  1857.                 // send once a second just to be sure
  1858. @@ -207,7 +209,7 @@
  1859.  
  1860.  bool CControls::OnMouseMove(float x, float y)
  1861.  {
  1862. -       if((m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)) ||
  1863. +       if((m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) ||
  1864.                 (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive()))
  1865.                 return false;
  1866.  
  1867. diff -Naur ../teeworlds/src/game/client/components/hud.cpp src/game/client/components/hud.cpp
  1868. --- ../teeworlds/src/game/client/components/hud.cpp     2012-06-26 16:53:53.356861181 +1000
  1869. +++ src/game/client/components/hud.cpp  2012-07-08 19:42:32.822259292 +1000
  1870. @@ -35,23 +35,21 @@
  1871.         {
  1872.                 char Buf[32];
  1873.                 int Time = 0;
  1874. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_WARMUP))
  1875. +               if(m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit && !m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer)
  1876.                 {
  1877. -                       Time = m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_GameStartTick)/Client()->GameTickSpeed());
  1878. +                       Time = m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed());
  1879.  
  1880. -                       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))
  1881. +                       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
  1882.                                 Time = 0;
  1883.                 }
  1884. -               else if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))
  1885. -                       Time = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer/Client()->GameTickSpeed();
  1886.                 else
  1887. -                       Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_GameStartTick)/Client()->GameTickSpeed();
  1888. +                       Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed();
  1889.  
  1890.                 str_format(Buf, sizeof(Buf), "%d:d", Time/60, Time%60);
  1891.                 float FontSize = 10.0f;
  1892.                 float w = TextRender()->TextWidth(0, FontSize, Buf, -1);
  1893.                 // last 60 sec red, last 10 sec blink
  1894. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit && Time <= 60 && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_WARMUP))
  1895. +               if(m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit && Time <= 60 && !m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer)
  1896.                 {
  1897.                         float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f;
  1898.                         TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha);
  1899. @@ -61,76 +59,15 @@
  1900.         }
  1901.  }
  1902.  
  1903. -void CHud::RenderPauseTimer()
  1904. +void CHud::RenderPauseNotification()
  1905.  {
  1906. -       if((m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED)) == GAMESTATEFLAG_PAUSED)
  1907. +       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED &&
  1908. +               !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  1909.         {
  1910. -               char aBuf[256];
  1911.                 const char *pText = Localize("Game paused");
  1912.                 float FontSize = 20.0f;
  1913. -               float w = TextRender()->TextWidth(0, FontSize, pText, -1);
  1914. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1);
  1915. -
  1916. -               FontSize = 16.0f;
  1917. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer == -1)
  1918. -               {
  1919. -                       int NotReadyCount = 0;
  1920. -                       for(int i = 0; i < MAX_CLIENTS; ++i)
  1921. -                       {
  1922. -                               if(m_pClient->m_Snap.m_paPlayerInfos[i] && m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team != TEAM_SPECTATORS &&
  1923. -                                       !(m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY))
  1924. -                                               ++NotReadyCount;
  1925. -                       }
  1926. -                       if(NotReadyCount == 1)
  1927. -                               str_format(aBuf, sizeof(aBuf), Localize("%d player not ready"), NotReadyCount);
  1928. -                       else if(NotReadyCount > 1)
  1929. -                               str_format(aBuf, sizeof(aBuf), Localize("%d players not ready"), NotReadyCount);
  1930. -                       else
  1931. -                               return;
  1932. -               }
  1933. -               else
  1934. -               {
  1935. -                       int Seconds = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer/SERVER_TICK_SPEED;
  1936. -                       if(Seconds < 5)
  1937. -                               str_format(aBuf, sizeof(aBuf), "%d.%d", Seconds, (m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer*10/SERVER_TICK_SPEED));
  1938. -                       else
  1939. -                               str_format(aBuf, sizeof(aBuf), "%d", Seconds);
  1940. -               }
  1941. -               w = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  1942. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1);
  1943. -       }
  1944. -}
  1945. -
  1946. -void CHud::RenderStartCountdown()
  1947. -{
  1948. -       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_STARTCOUNTDOWN)
  1949. -       {
  1950. -               char aBuf[256];
  1951. -               const char *pText = Localize("Game starts in");
  1952. -               float FontSize = 20.0f;
  1953. -               float w = TextRender()->TextWidth(0, FontSize, pText, -1);
  1954. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1);
  1955. -
  1956. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer == -1)
  1957. -                       return;
  1958. -              
  1959. -               FontSize = 16.0f;
  1960. -               int Seconds = (m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer+SERVER_TICK_SPEED-1)/SERVER_TICK_SPEED;
  1961. -               str_format(aBuf, sizeof(aBuf), "%d", Seconds);
  1962. -               w = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  1963. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1);
  1964. -       }
  1965. -}
  1966. -
  1967. -void CHud::RenderDeadNotification()
  1968. -{
  1969. -       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags == 0 && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS &&
  1970. -               (m_pClient->m_Snap.m_pLocalInfo->m_PlayerFlags&PLAYERFLAG_DEAD))
  1971. -       {
  1972. -               const char *pText = Localize("Wait for next round");
  1973. -               float FontSize = 16.0f;
  1974. -               float w = TextRender()->TextWidth(0, FontSize, pText, -1);
  1975. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, pText, -1);
  1976. +               float w = TextRender()->TextWidth(0, FontSize,pText, -1);
  1977. +               TextRender()->Text(0, 150.0f*Graphics()->ScreenAspect()+-w/2.0f, 50.0f, FontSize, pText, -1);
  1978.         }
  1979.  }
  1980.  
  1981. @@ -149,7 +86,7 @@
  1982.  void CHud::RenderScoreHud()
  1983.  {
  1984.         // render small score hud
  1985. -       if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)))
  1986. +       if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  1987.         {
  1988.                 int GameFlags = m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags;
  1989.                 float Whole = 300*Graphics()->ScreenAspect();
  1990. @@ -162,7 +99,6 @@
  1991.                         str_format(aScoreTeam[TEAM_BLUE], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameDataObj->m_TeamscoreBlue);
  1992.                         float aScoreTeamWidth[2] = { TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_RED], -1), TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_BLUE], -1) };
  1993.                         int FlagCarrier[2] = { m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierRed, m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue };
  1994. -                       int FlagDropTick[2] = { m_pClient->m_Snap.m_pGameDataObj->m_FlagDropTickRed, m_pClient->m_Snap.m_pGameDataObj->m_FlagDropTickBlue };
  1995.                         float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1));
  1996.                         float Split = 3.0f;
  1997.                         float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split;
  1998. @@ -185,7 +121,8 @@
  1999.  
  2000.                                 if(GameFlags&GAMEFLAG_FLAGS)
  2001.                                 {
  2002. -                                       int BlinkTimer = (FlagDropTick[t] != 0 && (Client()->GameTick()-FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20;
  2003. +                                       int BlinkTimer = (m_pClient->m_FlagDropTick[t] != 0 &&
  2004. +                                                                               (Client()->GameTick()-m_pClient->m_FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20;
  2005.                                         if(FlagCarrier[t] == FLAG_ATSTAND || (FlagCarrier[t] == FLAG_TAKEN && ((Client()->GameTick()/BlinkTimer)&1)))
  2006.                                         {
  2007.                                                 // draw flag
  2008. @@ -212,22 +149,6 @@
  2009.                                                         vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20));
  2010.                                         }
  2011.                                 }
  2012. -
  2013. -                               if(GameFlags&GAMEFLAG_SURVIVAL)
  2014. -                               {
  2015. -                                       // draw number of alive players
  2016. -                                       int Count = 0;
  2017. -                                       for(int i = 0; i < MAX_CLIENTS; ++i)
  2018. -                                       {
  2019. -                                               if(m_pClient->m_Snap.m_paPlayerInfos[i] && !(m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD) &&
  2020. -                                                       m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == t)
  2021. -                                                       ++Count;
  2022. -                                       }
  2023. -                                       char aBuf[32];
  2024. -                                       str_format(aBuf, sizeof(aBuf), Count==1?Localize("%d player left"):Localize("%d players left"), Count);
  2025. -                                       float w = TextRender()->TextWidth(0, 8.0f, aBuf, -1);
  2026. -                                       TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*20.0f-3.0f, 8.0f, aBuf, -1);
  2027. -                               }
  2028.                                 StartY += 8.0f;
  2029.                         }
  2030.                 }
  2031. @@ -274,8 +195,6 @@
  2032.                         float ScoreWidthMax = max(max(aScoreWidth[0], aScoreWidth[1]), TextRender()->TextWidth(0, 14.0f, "10", -1));
  2033.                         float Split = 3.0f, ImageSize = 16.0f, PosSize = 16.0f;
  2034.  
  2035. -                       // todo: add core hud for LMS
  2036. -
  2037.                         for(int t = 0; t < 2; t++)
  2038.                         {
  2039.                                 // draw box
  2040. @@ -321,40 +240,20 @@
  2041.  void CHud::RenderWarmupTimer()
  2042.  {
  2043.         // render warmup timer
  2044. -       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_WARMUP)
  2045. +       if(m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer)
  2046.         {
  2047. -               char aBuf[256];
  2048. +               char Buf[256];
  2049.                 float FontSize = 20.0f;
  2050.                 float w = TextRender()->TextWidth(0, FontSize, Localize("Warmup"), -1);
  2051.                 TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 50, FontSize, Localize("Warmup"), -1);
  2052.  
  2053. -               FontSize = 16.0f;
  2054. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer == -1)
  2055. -               {
  2056. -                       int NotReadyCount = 0;
  2057. -                       for(int i = 0; i < MAX_CLIENTS; ++i)
  2058. -                       {
  2059. -                               if(m_pClient->m_Snap.m_paPlayerInfos[i] && m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team != TEAM_SPECTATORS &&
  2060. -                                       !(m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY))
  2061. -                                               ++NotReadyCount;
  2062. -                       }
  2063. -                       if(NotReadyCount == 1)
  2064. -                               str_format(aBuf, sizeof(aBuf), Localize("%d player not ready"), NotReadyCount);
  2065. -                       else if(NotReadyCount > 1)
  2066. -                               str_format(aBuf, sizeof(aBuf), Localize("%d players not ready"), NotReadyCount);
  2067. -                       else
  2068. -                               str_format(aBuf, sizeof(aBuf), Localize("wait for more players"));
  2069. -               }
  2070. +               int Seconds = m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer/SERVER_TICK_SPEED;
  2071. +               if(Seconds < 5)
  2072. +                       str_format(Buf, sizeof(Buf), "%d.%d", Seconds, (m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer*10/SERVER_TICK_SPEED));
  2073.                 else
  2074. -               {
  2075. -                       int Seconds = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer/SERVER_TICK_SPEED;
  2076. -                       if(Seconds < 5)
  2077. -                               str_format(aBuf, sizeof(aBuf), "%d.%d", Seconds, (m_pClient->m_Snap.m_pGameInfoObj->m_GameStateTimer*10/SERVER_TICK_SPEED));
  2078. -                       else
  2079. -                               str_format(aBuf, sizeof(aBuf), "%d", Seconds);
  2080. -               }
  2081. -               w = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  2082. -               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, aBuf, -1);
  2083. +                       str_format(Buf, sizeof(Buf), "%d", Seconds);
  2084. +               w = TextRender()->TextWidth(0, FontSize, Buf, -1);
  2085. +               TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, Buf, -1);
  2086.         }
  2087.  }
  2088.  
  2089. @@ -553,7 +452,7 @@
  2090.  
  2091.         if(g_Config.m_ClShowhud)
  2092.         {
  2093. -               if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)))
  2094. +               if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  2095.                         RenderHealthAndAmmo(m_pClient->m_Snap.m_pLocalCharacter);
  2096.                 else if(m_pClient->m_Snap.m_SpecInfo.m_Active)
  2097.                 {
  2098. @@ -563,9 +462,7 @@
  2099.                 }
  2100.  
  2101.                 RenderGameTimer();
  2102. -               RenderPauseTimer();
  2103. -               RenderStartCountdown();
  2104. -               RenderDeadNotification();
  2105. +               RenderPauseNotification();
  2106.                 RenderSuddenDeath();
  2107.                 RenderScoreHud();
  2108.                 RenderWarmupTimer();
  2109. diff -Naur ../teeworlds/src/game/client/components/hud.h src/game/client/components/hud.h
  2110. --- ../teeworlds/src/game/client/components/hud.h       2012-06-26 16:53:53.356861181 +1000
  2111. +++ src/game/client/components/hud.h    2012-07-08 19:42:32.822259292 +1000
  2112. @@ -17,9 +17,7 @@
  2113.         void RenderVoting();
  2114.         void RenderHealthAndAmmo(const CNetObj_Character *pCharacter);
  2115.         void RenderGameTimer();
  2116. -       void RenderPauseTimer();
  2117. -       void RenderStartCountdown();
  2118. -       void RenderDeadNotification();
  2119. +       void RenderPauseNotification();
  2120.         void RenderSuddenDeath();
  2121.         void RenderScoreHud();
  2122.         void RenderSpectatorHud();
  2123. diff -Naur ../teeworlds/src/game/client/components/items.cpp src/game/client/components/items.cpp
  2124. --- ../teeworlds/src/game/client/components/items.cpp   2012-06-26 16:53:53.356861181 +1000
  2125. +++ src/game/client/components/items.cpp        2012-07-08 19:42:32.822259292 +1000
  2126. @@ -108,33 +108,29 @@
  2127.         vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
  2128.         float Angle = 0.0f;
  2129.         float Size = 64.0f;
  2130. -       const int c[] = {
  2131. -               SPRITE_PICKUP_HEALTH,
  2132. -               SPRITE_PICKUP_ARMOR,
  2133. -               SPRITE_PICKUP_GRENADE,
  2134. -               SPRITE_PICKUP_SHOTGUN,
  2135. -               SPRITE_PICKUP_LASER,
  2136. -               SPRITE_PICKUP_NINJA
  2137. -               };
  2138. -       RenderTools()->SelectSprite(c[pCurrent->m_Type]);
  2139. -
  2140. -       switch(pCurrent->m_Type)
  2141. -       {
  2142. -       case PICKUP_GRENADE:
  2143. -               Size = g_pData->m_Weapons.m_aId[WEAPON_GRENADE].m_VisualSize;
  2144. -               break;
  2145. -       case PICKUP_SHOTGUN:
  2146. -               Size = g_pData->m_Weapons.m_aId[WEAPON_SHOTGUN].m_VisualSize;
  2147. -               break;
  2148. -       case PICKUP_LASER:
  2149. -               Size = g_pData->m_Weapons.m_aId[WEAPON_LASER].m_VisualSize;
  2150. -               break;
  2151. -       case PICKUP_NINJA:
  2152. -               m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18));
  2153. -               Size *= 2.0f;
  2154. -               Pos.x -= 10.0f;
  2155. +       if (pCurrent->m_Type == POWERUP_WEAPON)
  2156. +       {
  2157. +               Angle = 0; //-pi/6;//-0.25f * pi * 2.0f;
  2158. +               RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_pSpriteBody);
  2159. +               Size = g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Subtype, 0, NUM_WEAPONS-1)].m_VisualSize;
  2160. +       }
  2161. +       else
  2162. +       {
  2163. +               const int c[] = {
  2164. +                       SPRITE_PICKUP_HEALTH,
  2165. +                       SPRITE_PICKUP_ARMOR,
  2166. +                       SPRITE_PICKUP_WEAPON,
  2167. +                       SPRITE_PICKUP_NINJA
  2168. +                       };
  2169. +               RenderTools()->SelectSprite(c[pCurrent->m_Type]);
  2170. +
  2171. +               if(c[pCurrent->m_Type] == SPRITE_PICKUP_NINJA)
  2172. +               {
  2173. +                       m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18));
  2174. +                       Size *= 2.0f;
  2175. +                       Pos.x -= 10.0f;
  2176. +               }
  2177.         }
  2178. -      
  2179.  
  2180.         Graphics()->QuadsSetRotation(Angle);
  2181.  
  2182. diff -Naur ../teeworlds/src/game/client/components/maplayers.cpp src/game/client/components/maplayers.cpp
  2183. --- ../teeworlds/src/game/client/components/maplayers.cpp       2012-06-26 16:53:53.356861181 +1000
  2184. +++ src/game/client/components/maplayers.cpp    2012-07-08 19:42:32.822259292 +1000
  2185. @@ -104,8 +104,8 @@
  2186.                 {
  2187.                         if(pItem->m_Version < 2 || pItem->m_Synchronized)
  2188.                         {
  2189. -                               s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(),
  2190. -                                                       (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(),
  2191. +                               s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
  2192. +                                                       (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
  2193.                                                         pThis->Client()->IntraGameTick());
  2194.                         }
  2195.                         else
  2196. diff -Naur ../teeworlds/src/game/client/components/menus_browser.cpp src/game/client/components/menus_browser.cpp
  2197. --- ../teeworlds/src/game/client/components/menus_browser.cpp   2012-06-26 16:53:53.360863645 +1000
  2198. +++ src/game/client/components/menus_browser.cpp        2012-07-08 19:42:32.826259590 +1000
  2199. @@ -225,7 +225,7 @@
  2200.         {
  2201.                 int ItemIndex = i;
  2202.                 const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
  2203. -               NumPlayers += g_Config.m_BrFilterSpectators ? pItem->m_NumPlayers : pItem->m_NumClients;
  2204. +               NumPlayers += pItem->m_NumPlayers;
  2205.                 CUIRect Row;
  2206.                 CUIRect SelectHitBox;
  2207.  
  2208. @@ -314,9 +314,7 @@
  2209.                         {
  2210.                                 if(     str_comp(pItem->m_aGameType, "DM") == 0 ||
  2211.                                         str_comp(pItem->m_aGameType, "TDM") == 0 ||
  2212. -                                       str_comp(pItem->m_aGameType, "CTF") == 0 ||
  2213. -                                       str_comp(pItem->m_aGameType, "LMS") == 0 ||
  2214. -                                       str_comp(pItem->m_aGameType, "SUR") == 0)
  2215. +                                       str_comp(pItem->m_aGameType, "CTF") == 0)
  2216.                                 {
  2217.                                         // pure server
  2218.                                 }
  2219. diff -Naur ../teeworlds/src/game/client/components/menus.cpp src/game/client/components/menus.cpp
  2220. --- ../teeworlds/src/game/client/components/menus.cpp   2012-06-26 16:53:53.360863645 +1000
  2221. +++ src/game/client/components/menus.cpp        2012-07-08 19:42:32.822259292 +1000
  2222. @@ -539,7 +539,7 @@
  2223.  
  2224.                 Box.VSplitLeft(100.0f, &Button, &Box);
  2225.                 static int s_InternetButton=0;
  2226. -               if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), m_ActivePage==PAGE_INTERNET, &Button, CUI::CORNER_TL) && m_ActivePage!=PAGE_INTERNET)
  2227. +               if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), m_ActivePage==PAGE_INTERNET, &Button, CUI::CORNER_TL))
  2228.                 {
  2229.                         ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
  2230.                         NewPage = PAGE_INTERNET;
  2231. @@ -548,7 +548,7 @@
  2232.                 //Box.VSplitLeft(4.0f, 0, &Box);
  2233.                 Box.VSplitLeft(80.0f, &Button, &Box);
  2234.                 static int s_LanButton=0;
  2235. -               if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), m_ActivePage==PAGE_LAN, &Button, 0) && m_ActivePage!=PAGE_LAN)
  2236. +               if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), m_ActivePage==PAGE_LAN, &Button, 0))
  2237.                 {
  2238.                         ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
  2239.                         NewPage = PAGE_LAN;
  2240. @@ -557,7 +557,7 @@
  2241.                 //box.VSplitLeft(4.0f, 0, &box);
  2242.                 Box.VSplitLeft(110.0f, &Button, &Box);
  2243.                 static int s_FavoritesButton=0;
  2244. -               if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR) && m_ActivePage!=PAGE_FAVORITES)
  2245. +               if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR))
  2246.                 {
  2247.                         ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
  2248.                         NewPage = PAGE_FAVORITES;
  2249. @@ -566,7 +566,7 @@
  2250.                 Box.VSplitLeft(4.0f*5, 0, &Box);
  2251.                 Box.VSplitLeft(100.0f, &Button, &Box);
  2252.                 static int s_DemosButton=0;
  2253. -               if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T) && m_ActivePage!=PAGE_DEMOS)
  2254. +               if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T))
  2255.                 {
  2256.                         DemolistPopulate();
  2257.                         NewPage = PAGE_DEMOS;
  2258. @@ -1045,7 +1045,7 @@
  2259.                                         }
  2260.  
  2261.                                         // update download speed
  2262. -                                       float Diff = (Client()->MapDownloadAmount()-m_DownloadLastCheckSize)/((int)((Now-m_DownloadLastCheckTime)/time_freq()));
  2263. +                                       float Diff = Client()->MapDownloadAmount()-m_DownloadLastCheckSize;
  2264.                                         float StartDiff = m_DownloadLastCheckSize-0.0f;
  2265.                                         if(StartDiff+Diff > 0.0f)
  2266.                                                 m_DownloadSpeed = (Diff/(StartDiff+Diff))*(Diff/1.0f) + (StartDiff/(Diff+StartDiff))*m_DownloadSpeed;
  2267. diff -Naur ../teeworlds/src/game/client/components/menus.h src/game/client/components/menus.h
  2268. --- ../teeworlds/src/game/client/components/menus.h     2012-07-08 00:31:07.985177225 +1000
  2269. +++ src/game/client/components/menus.h  2012-07-08 19:42:32.826259590 +1000
  2270. @@ -218,11 +218,11 @@
  2271.                                 return false;
  2272.                         else
  2273.                         {
  2274. -                               int Result = str_comp_nocase(m_pFriendInfo->m_aName, Other.m_pFriendInfo->m_aName);
  2275. +                               int Result = str_comp(m_pFriendInfo->m_aName, Other.m_pFriendInfo->m_aName);
  2276.                                 if(Result)
  2277.                                         return Result < 0;
  2278.                                 else
  2279. -                                       return str_comp_nocase(m_pFriendInfo->m_aClan, Other.m_pFriendInfo->m_aClan) < 0;
  2280. +                                       return str_comp(m_pFriendInfo->m_aClan, Other.m_pFriendInfo->m_aClan) < 0;
  2281.                         }
  2282.                 }
  2283.         };
  2284. diff -Naur ../teeworlds/src/game/client/components/menus_ingame.cpp src/game/client/components/menus_ingame.cpp
  2285. --- ../teeworlds/src/game/client/components/menus_ingame.cpp    2012-06-26 16:53:53.364862128 +1000
  2286. +++ src/game/client/components/menus_ingame.cpp 2012-07-08 19:42:32.826259590 +1000
  2287. @@ -183,7 +183,7 @@
  2288.                 ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
  2289.                 Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
  2290.                 Button.VSplitLeft(Button.h, &Button, 0);
  2291. -               if(g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
  2292. +               if(&g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
  2293.                         DoButton_Toggle(&s_aPlayerIDs[Index][0], 1, &Button, false);
  2294.                 else
  2295.                         if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button, true))
  2296. diff -Naur ../teeworlds/src/game/client/components/menus_settings.cpp src/game/client/components/menus_settings.cpp
  2297. --- ../teeworlds/src/game/client/components/menus_settings.cpp  2012-07-08 00:31:07.989177105 +1000
  2298. +++ src/game/client/components/menus_settings.cpp       2012-07-08 19:42:32.830259121 +1000
  2299. @@ -433,7 +433,7 @@
  2300.         { "Pistol", "+weapon2", 0 },
  2301.         { "Shotgun", "+weapon3", 0 },
  2302.         { "Grenade", "+weapon4", 0 },
  2303. -       { "Laser", "+weapon5", 0 },
  2304. +       { "Rifle", "+weapon5", 0 },
  2305.         { "Next weapon", "+nextweapon", 0 },
  2306.         { "Prev. weapon", "+prevweapon", 0 },
  2307.         { "Vote yes", "vote yes", 0 },
  2308. @@ -450,15 +450,13 @@
  2309.         { "Screenshot", "screenshot", 0 },
  2310.         { "Scoreboard", "+scoreboard", 0 },
  2311.         { "Respawn", "kill", 0 },
  2312. -       { "Ready", "ready_change", 0 },
  2313.  };
  2314.  
  2315.  /*     This is for scripts/update_localization.py to work, don't remove!
  2316.         Localize("Move left");Localize("Move right");Localize("Jump");Localize("Fire");Localize("Hook");Localize("Hammer");
  2317. -       Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Laser");Localize("Next weapon");Localize("Prev. weapon");
  2318. +       Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Rifle");Localize("Next weapon");Localize("Prev. weapon");
  2319.         Localize("Vote yes");Localize("Vote no");Localize("Chat");Localize("Team chat");Localize("Show chat");Localize("Emoticon");
  2320. -       Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console");
  2321. -       Localize("Screenshot");Localize("Scoreboard");Localize("Respawn");Localize("Ready");
  2322. +       Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console");Localize("Screenshot");Localize("Scoreboard");Localize("Respawn");
  2323.  */
  2324.  
  2325.  const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo);
  2326. @@ -615,7 +613,6 @@
  2327.         static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth;
  2328.         static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight;
  2329.         static int s_GfxColorDepth = g_Config.m_GfxColorDepth;
  2330. -       static int s_GfxBorderless = g_Config.m_GfxBorderless;
  2331.         static int s_GfxFullscreen = g_Config.m_GfxFullscreen;
  2332.         static int s_GfxVsync = g_Config.m_GfxVsync;
  2333.         static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples;
  2334. @@ -671,20 +668,9 @@
  2335.  
  2336.         // switches
  2337.         MainView.HSplitTop(20.0f, &Button, &MainView);
  2338. -       if(DoButton_CheckBox(&g_Config.m_GfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
  2339. -       {
  2340. -               g_Config.m_GfxBorderless ^= 1;
  2341. -               if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
  2342. -                       g_Config.m_GfxFullscreen = 0;
  2343. -               CheckSettings = true;
  2344. -       }
  2345. -
  2346. -       MainView.HSplitTop(20.0f, &Button, &MainView);
  2347.         if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
  2348.         {
  2349.                 g_Config.m_GfxFullscreen ^= 1;
  2350. -               if(g_Config.m_GfxFullscreen && g_Config.m_GfxBorderless)
  2351. -                       g_Config.m_GfxBorderless = 0;
  2352.                 CheckSettings = true;
  2353.         }
  2354.  
  2355. @@ -727,7 +713,6 @@
  2356.                 if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth &&
  2357.                         s_GfxScreenHeight == g_Config.m_GfxScreenHeight &&
  2358.                         s_GfxColorDepth == g_Config.m_GfxColorDepth &&
  2359. -                       s_GfxBorderless == g_Config.m_GfxBorderless &&
  2360.                         s_GfxFullscreen == g_Config.m_GfxFullscreen &&
  2361.                         s_GfxVsync == g_Config.m_GfxVsync &&
  2362.                         s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
  2363. @@ -796,13 +781,10 @@
  2364.         if(DoButton_CheckBox(&g_Config.m_SndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button))
  2365.         {
  2366.                 g_Config.m_SndMusic ^= 1;
  2367. -               if(Client()->State() == IClient::STATE_OFFLINE)
  2368. -               {
  2369. -                       if(g_Config.m_SndMusic)
  2370. -                               m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
  2371. -                       else
  2372. -                               m_pClient->m_pSounds->Stop(SOUND_MENU);
  2373. -               }
  2374. +               if(g_Config.m_SndMusic)
  2375. +                       m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
  2376. +               else
  2377. +                       m_pClient->m_pSounds->Stop(SOUND_MENU);
  2378.         }
  2379.  
  2380.         MainView.HSplitTop(20.0f, &Button, &MainView);
  2381. diff -Naur ../teeworlds/src/game/client/components/players.cpp src/game/client/components/players.cpp
  2382. --- ../teeworlds/src/game/client/components/players.cpp 2012-06-26 16:53:53.368860821 +1000
  2383. +++ src/game/client/components/players.cpp      2012-07-08 19:42:32.830259121 +1000
  2384. @@ -106,8 +106,7 @@
  2385.         // use preditect players if needed
  2386.         if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
  2387.         {
  2388. -               if(!m_pClient->m_Snap.m_pLocalCharacter ||
  2389. -                       (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)))
  2390. +               if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  2391.                 {
  2392.                 }
  2393.                 else
  2394. @@ -240,8 +239,7 @@
  2395.         // use preditect players if needed
  2396.         if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
  2397.         {
  2398. -               if(!m_pClient->m_Snap.m_pLocalCharacter ||
  2399. -                       (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)))
  2400. +               if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  2401.                 {
  2402.                 }
  2403.                 else
  2404. @@ -487,7 +485,7 @@
  2405.         RenderInfo.m_ColorFeet.a = 1.0f;
  2406.         RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position);
  2407.  
  2408. -       if(pInfo.m_PlayerFlags&PLAYERFLAG_CHATTING)
  2409. +       if(Player.m_PlayerFlags&PLAYERFLAG_CHATTING)
  2410.         {
  2411.                 Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
  2412.                 Graphics()->QuadsBegin();
  2413. diff -Naur ../teeworlds/src/game/client/components/scoreboard.cpp src/game/client/components/scoreboard.cpp
  2414. --- ../teeworlds/src/game/client/components/scoreboard.cpp      2012-06-26 16:53:53.368860821 +1000
  2415. +++ src/game/client/components/scoreboard.cpp   2012-07-08 19:42:32.830259121 +1000
  2416. @@ -70,10 +70,10 @@
  2417.                         str_format(aBuf, sizeof(aBuf), Localize("Time limit: %d min"), m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit);
  2418.                         TextRender()->Text(0, x+230.0f, y, 20.0f, aBuf, -1);
  2419.                 }
  2420. -               if(m_pClient->m_Snap.m_pGameInfoObj->m_MatchNum && m_pClient->m_Snap.m_pGameInfoObj->m_MatchCurrent)
  2421. +               if(m_pClient->m_Snap.m_pGameInfoObj->m_RoundNum && m_pClient->m_Snap.m_pGameInfoObj->m_RoundCurrent)
  2422.                 {
  2423.                         char aBuf[64];
  2424. -                       str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Match"), m_pClient->m_Snap.m_pGameInfoObj->m_MatchCurrent, m_pClient->m_Snap.m_pGameInfoObj->m_MatchNum);
  2425. +                       str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Round"), m_pClient->m_Snap.m_pGameInfoObj->m_RoundCurrent, m_pClient->m_Snap.m_pGameInfoObj->m_RoundNum);
  2426.                         float tw = TextRender()->TextWidth(0, 20.0f, aBuf, -1);
  2427.                         TextRender()->Text(0, x+w-tw-10.0f, y, 20.0f, aBuf, -1);
  2428.                 }
  2429. @@ -98,11 +98,9 @@
  2430.  
  2431.         // spectator names
  2432.         y += 30.0f;
  2433. +       char aBuffer[1024*4];
  2434. +       aBuffer[0] = 0;
  2435.         bool Multiple = false;
  2436. -       CTextCursor Cursor;
  2437. -       TextRender()->SetCursor(&Cursor, x+10.0f, y, 22.0f, TEXTFLAG_RENDER);
  2438. -       Cursor.m_LineWidth = w-20.0f;
  2439. -       Cursor.m_MaxLines = 4;
  2440.         for(int i = 0; i < MAX_CLIENTS; ++i)
  2441.         {
  2442.                 const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paPlayerInfos[i];
  2443. @@ -110,13 +108,15 @@
  2444.                         continue;
  2445.  
  2446.                 if(Multiple)
  2447. -                       TextRender()->TextEx(&Cursor, ", ", -1);
  2448. -               if(pInfo->m_PlayerFlags&PLAYERFLAG_WATCHING)
  2449. -                       TextRender()->TextColor(1.0f, 1.0f, 0.0f, 1.0f);
  2450. -               TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aName, -1);
  2451. -               TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
  2452. +                       str_append(aBuffer, ", ", sizeof(aBuffer));
  2453. +               str_append(aBuffer, m_pClient->m_aClients[pInfo->m_ClientID].m_aName, sizeof(aBuffer));
  2454.                 Multiple = true;
  2455.         }
  2456. +       CTextCursor Cursor;
  2457. +       TextRender()->SetCursor(&Cursor, x+10.0f, y, 22.0f, TEXTFLAG_RENDER);
  2458. +       Cursor.m_LineWidth = w-20.0f;
  2459. +       Cursor.m_MaxLines = 4;
  2460. +       TextRender()->TextEx(&Cursor, aBuffer, -1);
  2461.  }
  2462.  
  2463.  void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle)
  2464. @@ -124,6 +124,13 @@
  2465.         if(Team == TEAM_SPECTATORS)
  2466.                 return;
  2467.  
  2468. +       bool upper16 = false;
  2469. +       if (Team == -3)
  2470. +       {
  2471. +               upper16 = true;
  2472. +               Team = 0;
  2473. +       }
  2474. +
  2475.         float h = 760.0f;
  2476.  
  2477.         // background
  2478. @@ -140,8 +147,6 @@
  2479.         {
  2480.                 if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
  2481.                         pTitle = Localize("Game over");
  2482. -               else if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_ROUNDOVER)
  2483. -                       pTitle = Localize("Round over");
  2484.                 else
  2485.                         pTitle = Localize("Score board");
  2486.         }
  2487. @@ -217,101 +222,81 @@
  2488.         float FontSize = 24.0f;
  2489.         CTextCursor Cursor;
  2490.  
  2491. -       for(int RenderDead = 0; RenderDead < 2; ++RenderDead)
  2492. +       int rendered = upper16?-16:0;
  2493. +       for(int i = 0; i < MAX_CLIENTS; i++)
  2494.         {
  2495. -               float ColorAlpha = RenderDead ? 0.5f : 1.0f;
  2496. -               TextRender()->TextColor(1.0f, 1.0f, 1.0f, ColorAlpha);
  2497. -               for(int i = 0; i < MAX_CLIENTS; i++)
  2498. -               {
  2499. -                       // make sure that we render the correct team
  2500. -                       const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByScore[i];
  2501. -                       if(!pInfo || pInfo->m_Team != Team || (!RenderDead && (pInfo->m_PlayerFlags&PLAYERFLAG_DEAD)) || (RenderDead && !(pInfo->m_PlayerFlags&PLAYERFLAG_DEAD)))
  2502. -                               continue;
  2503. +               // make sure that we render the correct team
  2504. +               const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByScore[i];
  2505. +               if(!pInfo || pInfo->m_Team != Team)
  2506. +                       continue;
  2507.  
  2508. -                       // background so it's easy to find the local player or the followed one in spectator mode
  2509. -                       if(pInfo->m_Local || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID))
  2510. -                       {
  2511. -                               Graphics()->TextureSet(-1);
  2512. -                               Graphics()->QuadsBegin();
  2513. -                               Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f*ColorAlpha);
  2514. -                               RenderTools()->DrawRoundRect(x, y, w-20.0f, LineHeight, 15.0f);
  2515. -                               Graphics()->QuadsEnd();
  2516. -                       }
  2517. +               if (rendered++ < 0) continue;
  2518.  
  2519. -                       // score
  2520. -                       str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Score, -999, 999));
  2521. -                       tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  2522. -                       TextRender()->SetCursor(&Cursor, ScoreOffset+ScoreLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2523. -                       Cursor.m_LineWidth = ScoreLength;
  2524. -                       TextRender()->TextEx(&Cursor, aBuf, -1);
  2525. -
  2526. -                       // flag
  2527. -                       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_FLAGS &&
  2528. -                               m_pClient->m_Snap.m_pGameDataObj && (m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierRed == pInfo->m_ClientID ||
  2529. -                               m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue == pInfo->m_ClientID))
  2530. -                       {
  2531. -                               Graphics()->BlendNormal();
  2532. -                               Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
  2533. -                               Graphics()->QuadsBegin();
  2534. -
  2535. -                               RenderTools()->SelectSprite(pInfo->m_Team==TEAM_RED ? SPRITE_FLAG_BLUE : SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
  2536. -
  2537. -                               float Size = LineHeight;
  2538. -                               IGraphics::CQuadItem QuadItem(TeeOffset+0.0f, y-5.0f-Spacing/2.0f, Size/2.0f, Size);
  2539. -                               Graphics()->QuadsDrawTL(&QuadItem, 1);
  2540. -                               Graphics()->QuadsEnd();
  2541. -                       }
  2542. +               // background so it's easy to find the local player or the followed one in spectator mode
  2543. +               if(pInfo->m_Local || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID))
  2544. +               {
  2545. +                       Graphics()->TextureSet(-1);
  2546. +                       Graphics()->QuadsBegin();
  2547. +                       Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
  2548. +                       RenderTools()->DrawRoundRect(x, y, w-20.0f, LineHeight, 15.0f);
  2549. +                       Graphics()->QuadsEnd();
  2550. +               }
  2551.  
  2552. -                       // avatar
  2553. -                       if(RenderDead)
  2554. -                       {
  2555. -                               Graphics()->BlendNormal();
  2556. -                               Graphics()->TextureSet(g_pData->m_aImages[IMAGE_DEADTEE].m_Id);
  2557. -                               Graphics()->QuadsBegin();
  2558. -                               IGraphics::CQuadItem QuadItem(TeeOffset, y, 64*TeeSizeMod, 64*TeeSizeMod);
  2559. -                               Graphics()->QuadsDrawTL(&QuadItem, 1);
  2560. -                               Graphics()->QuadsEnd();
  2561. -                       }
  2562. -                       else
  2563. -                       {
  2564. -                               CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo;
  2565. -                               TeeInfo.m_Size *= TeeSizeMod;
  2566. -                               RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(TeeOffset+TeeLength/2, y+LineHeight/2));
  2567. -                       }
  2568. +               // score
  2569. +               str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Score, -999, 999));
  2570. +               tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  2571. +               TextRender()->SetCursor(&Cursor, ScoreOffset+ScoreLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2572. +               Cursor.m_LineWidth = ScoreLength;
  2573. +               TextRender()->TextEx(&Cursor, aBuf, -1);
  2574. +
  2575. +               // flag
  2576. +               if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_FLAGS &&
  2577. +                       m_pClient->m_Snap.m_pGameDataObj && (m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierRed == pInfo->m_ClientID ||
  2578. +                       m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue == pInfo->m_ClientID))
  2579. +               {
  2580. +                       Graphics()->BlendNormal();
  2581. +                       Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
  2582. +                       Graphics()->QuadsBegin();
  2583. +
  2584. +                       RenderTools()->SelectSprite(pInfo->m_Team==TEAM_RED ? SPRITE_FLAG_BLUE : SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
  2585. +
  2586. +                       float Size = LineHeight;
  2587. +                       IGraphics::CQuadItem QuadItem(TeeOffset+0.0f, y-5.0f-Spacing/2.0f, Size/2.0f, Size);
  2588. +                       Graphics()->QuadsDrawTL(&QuadItem, 1);
  2589. +                       Graphics()->QuadsEnd();
  2590. +               }
  2591.  
  2592. -                       // name
  2593. -                       // todo: improve visual player ready state
  2594. -                       if(!(pInfo->m_PlayerFlags&PLAYERFLAG_READY))
  2595. -                               TextRender()->TextColor(1.0f, 0.5f, 0.5f, ColorAlpha);
  2596. -                       else if(RenderDead && pInfo->m_PlayerFlags&PLAYERFLAG_WATCHING)
  2597. -                               TextRender()->TextColor(1.0f, 1.0f, 0.0f, ColorAlpha);
  2598. -                       TextRender()->SetCursor(&Cursor, NameOffset, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2599. -                       Cursor.m_LineWidth = NameLength;
  2600. -                       TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aName, -1);
  2601. -                       TextRender()->TextColor(1.0f, 1.0f, 1.0f, ColorAlpha);
  2602. -
  2603. -                       // clan
  2604. -                       tw = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
  2605. -                       TextRender()->SetCursor(&Cursor, ClanOffset+ClanLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2606. -                       Cursor.m_LineWidth = ClanLength;
  2607. -                       TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
  2608. -
  2609. -                       // country flag
  2610. -                       vec4 Color(1.0f, 1.0f, 1.0f, 0.5f*ColorAlpha);
  2611. -                       m_pClient->m_pCountryFlags->Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color,
  2612. -                                                                                               CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f);
  2613. -
  2614. -                       // ping
  2615. -                       str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Latency, 0, 1000));
  2616. -                       tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  2617. -                       TextRender()->SetCursor(&Cursor, PingOffset+PingLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2618. -                       Cursor.m_LineWidth = PingLength;
  2619. -                       TextRender()->TextEx(&Cursor, aBuf, -1);
  2620. +               // avatar
  2621. +               CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo;
  2622. +               TeeInfo.m_Size *= TeeSizeMod;
  2623. +               RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(TeeOffset+TeeLength/2, y+LineHeight/2));
  2624. +
  2625. +               // name
  2626. +               TextRender()->SetCursor(&Cursor, NameOffset, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2627. +               Cursor.m_LineWidth = NameLength;
  2628. +               TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aName, -1);
  2629.  
  2630. -                       y += LineHeight+Spacing;
  2631. -               }
  2632. +               // clan
  2633. +               tw = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
  2634. +               TextRender()->SetCursor(&Cursor, ClanOffset+ClanLength/2-tw/2, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2635. +               Cursor.m_LineWidth = ClanLength;
  2636. +               TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1);
  2637. +
  2638. +               // country flag
  2639. +               vec4 Color(1.0f, 1.0f, 1.0f, 0.5f);
  2640. +               m_pClient->m_pCountryFlags->Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color,
  2641. +                                                                                       CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f);
  2642. +
  2643. +               // ping
  2644. +               str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Latency, 0, 1000));
  2645. +               tw = TextRender()->TextWidth(0, FontSize, aBuf, -1);
  2646. +               TextRender()->SetCursor(&Cursor, PingOffset+PingLength-tw, y+Spacing, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
  2647. +               Cursor.m_LineWidth = PingLength;
  2648. +               TextRender()->TextEx(&Cursor, aBuf, -1);
  2649. +
  2650. +               y += LineHeight+Spacing;
  2651. +               if (rendered == 16) break;
  2652.         }
  2653. -       TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
  2654.  }
  2655.  
  2656.  void CScoreboard::RenderRecordingNotification(float x)
  2657. @@ -360,13 +345,22 @@
  2658.         if(m_pClient->m_Snap.m_pGameInfoObj)
  2659.         {
  2660.                 if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS))
  2661. -                       RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
  2662. +               {
  2663. +                       if(m_pClient->m_Snap.m_aTeamSize[0] > 16)
  2664. +                       {
  2665. +                               RenderScoreboard(Width/2-w-5.0f, 150.0f, w, 0, 0);
  2666. +                               RenderScoreboard(Width/2+5.0f, 150.0f, w, -3, 0);
  2667. +                       } else
  2668. +                       {
  2669. +                               RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
  2670. +                       }
  2671. +               }
  2672.                 else
  2673.                 {
  2674.                         const char *pRedClanName = GetClanName(TEAM_RED);
  2675.                         const char *pBlueClanName = GetClanName(TEAM_BLUE);
  2676.  
  2677. -                       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
  2678. +                       if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER && m_pClient->m_Snap.m_pGameDataObj)
  2679.                         {
  2680.                                 char aText[256];
  2681.                                 str_copy(aText, Localize("Draw!"), sizeof(aText));
  2682. @@ -389,14 +383,6 @@
  2683.                                 float w = TextRender()->TextWidth(0, 86.0f, aText, -1);
  2684.                                 TextRender()->Text(0, Width/2-w/2, 39, 86.0f, aText, -1);
  2685.                         }
  2686. -                       else if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_ROUNDOVER)
  2687. -                       {
  2688. -                               char aText[256];
  2689. -                               str_copy(aText, Localize("Round over!"), sizeof(aText));
  2690. -
  2691. -                               float w = TextRender()->TextWidth(0, 86.0f, aText, -1);
  2692. -                               TextRender()->Text(0, Width/2-w/2, 39, 86.0f, aText, -1);
  2693. -                       }
  2694.  
  2695.                         RenderScoreboard(Width/2-w-5.0f, 150.0f, w, TEAM_RED, pRedClanName ? pRedClanName : Localize("Red team"));
  2696.                         RenderScoreboard(Width/2+5.0f, 150.0f, w, TEAM_BLUE, pBlueClanName ? pBlueClanName : Localize("Blue team"));
  2697. @@ -416,13 +402,13 @@
  2698.  
  2699.         if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS)
  2700.         {
  2701. -               // we are not a spectator, check if we are dead, don't follow a player and the game isn't paused
  2702. -               if(!m_pClient->m_Snap.m_pLocalCharacter && !m_pClient->m_Snap.m_SpecInfo.m_Active && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
  2703. +               // we are not a spectator, check if we are dead
  2704. +               if(!m_pClient->m_Snap.m_pLocalCharacter)
  2705.                         return true;
  2706.         }
  2707.  
  2708.         // if the game is over
  2709. -       if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER))
  2710. +       if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
  2711.                 return true;
  2712.  
  2713.         return false;
  2714. diff -Naur ../teeworlds/src/game/client/components/skins.h src/game/client/components/skins.h
  2715. --- ../teeworlds/src/game/client/components/skins.h     2012-07-08 00:31:07.989177105 +1000
  2716. +++ src/game/client/components/skins.h  2012-07-08 19:28:03.394259187 +1000
  2717. @@ -17,7 +17,7 @@
  2718.                 char m_aName[24];
  2719.                 vec3 m_BloodColor;
  2720.  
  2721. -               bool operator<(const CSkin &Other) { return str_comp_nocase(m_aName, Other.m_aName) < 0; }
  2722. +               bool operator<(const CSkin &Other) { return str_comp(m_aName, Other.m_aName) < 0; }
  2723.         };
  2724.  
  2725.         void OnInit();
  2726. diff -Naur ../teeworlds/src/game/client/components/spectator.cpp src/game/client/components/spectator.cpp
  2727. --- ../teeworlds/src/game/client/components/spectator.cpp       2012-06-26 16:53:53.368860821 +1000
  2728. +++ src/game/client/components/spectator.cpp    2012-07-08 19:28:03.394259187 +1000
  2729. @@ -195,33 +195,28 @@
  2730.         float LineHeight = 60.0f;
  2731.         bool Selected = false;
  2732.  
  2733. -       if(m_pClient->m_Snap.m_pLocalInfo->m_Team == TEAM_SPECTATORS)
  2734. +       if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
  2735.         {
  2736. -               if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
  2737. -               {
  2738. -                       Graphics()->TextureSet(-1);
  2739. -                       Graphics()->QuadsBegin();
  2740. -                       Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
  2741. -                       RenderTools()->DrawRoundRect(Width/2.0f-280.0f, Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f);
  2742. -                       Graphics()->QuadsEnd();
  2743. -               }
  2744. +               Graphics()->TextureSet(-1);
  2745. +               Graphics()->QuadsBegin();
  2746. +               Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
  2747. +               RenderTools()->DrawRoundRect(Width/2.0f-280.0f, Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f);
  2748. +               Graphics()->QuadsEnd();
  2749. +       }
  2750.  
  2751. -               if(m_SelectorMouse.x >= -280.0f && m_SelectorMouse.x <= -10.0f &&
  2752. -                       m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
  2753. -               {
  2754. -                       m_SelectedSpectatorID = SPEC_FREEVIEW;
  2755. -                       Selected = true;
  2756. -               }
  2757. -               TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f);
  2758. -               TextRender()->Text(0, Width/2.0f-240.0f, Height/2.0f-265.0f, FontSize, Localize("Free-View"), -1);
  2759. +       if(m_SelectorMouse.x >= -280.0f && m_SelectorMouse.x <= -10.0f &&
  2760. +               m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
  2761. +       {
  2762. +               m_SelectedSpectatorID = SPEC_FREEVIEW;
  2763. +               Selected = true;
  2764.         }
  2765. +       TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f);
  2766. +       TextRender()->Text(0, Width/2.0f-240.0f, Height/2.0f-265.0f, FontSize, Localize("Free-View"), -1);
  2767.  
  2768.         float x = -270.0f, y = StartY;
  2769.         for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i)
  2770.         {
  2771. -               if(!m_pClient->m_Snap.m_paPlayerInfos[i] || m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS ||
  2772. -                       (m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS && (m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD ||
  2773. -                       m_pClient->m_Snap.m_pLocalInfo->m_Team != m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team || i == m_pClient->m_Snap.m_LocalClientID)))
  2774. +               if(!m_pClient->m_Snap.m_paPlayerInfos[i] || m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS)
  2775.                         continue;
  2776.  
  2777.                 if(++Count%9 == 0)
  2778. diff -Naur ../teeworlds/src/game/client/components/voting.cpp src/game/client/components/voting.cpp
  2779. --- ../teeworlds/src/game/client/components/voting.cpp  2012-06-26 16:53:53.372860980 +1000
  2780. +++ src/game/client/components/voting.cpp       2012-07-08 19:28:03.394259187 +1000
  2781. @@ -120,12 +120,7 @@
  2782.  CVoting::CVoting()
  2783.  {
  2784.         ClearOptions();
  2785. -      
  2786. -       m_Closetime = 0;
  2787. -       m_aDescription[0] = 0;
  2788. -       m_aReason[0] = 0;
  2789. -       m_Yes = m_No = m_Pass = m_Total = 0;
  2790. -       m_Voted = 0;
  2791. +       OnReset();
  2792.  }
  2793.  
  2794.  void CVoting::AddOption(const char *pDescription)
  2795. @@ -169,9 +164,6 @@
  2796.  
  2797.  void CVoting::OnReset()
  2798.  {
  2799. -       if(Client()->State() == IClient::STATE_LOADING) // do not reset active vote while connecting
  2800. -               return;
  2801. -
  2802.         m_Closetime = 0;
  2803.         m_aDescription[0] = 0;
  2804.         m_aReason[0] = 0;
  2805. diff -Naur ../teeworlds/src/game/client/gameclient.cpp src/game/client/gameclient.cpp
  2806. --- ../teeworlds/src/game/client/gameclient.cpp 2012-06-26 16:53:53.372860980 +1000
  2807. +++ src/game/client/gameclient.cpp      2012-07-08 19:48:22.537766616 +1000
  2808. @@ -177,7 +177,6 @@
  2809.         // add the some console commands
  2810.         Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team");
  2811.         Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself");
  2812. -       Console()->Register("ready_change", "", CFGFLAG_CLIENT, ConReadyChange, this, "Change ready state");
  2813.  
  2814.         // register server dummy commands for tab completion
  2815.         Console()->Register("tune", "si", CFGFLAG_SERVER, 0, 0, "Tune variable to value");
  2816. @@ -194,6 +193,7 @@
  2817.         Console()->Register("force_vote", "ss?r", CFGFLAG_SERVER, 0, 0, "Force a voting option");
  2818.         Console()->Register("clear_votes", "", CFGFLAG_SERVER, 0, 0, "Clears the voting options");
  2819.         Console()->Register("vote", "r", CFGFLAG_SERVER, 0, 0, "Force a vote to yes/no");
  2820. +       Console()->Register("spin", "i", CFGFLAG_SERVER, 0, 0, "If somone is using spin bot, Use this on them.");
  2821.         Console()->Register("swap_teams", "", CFGFLAG_SERVER, 0, 0, "Swap the current teams");
  2822.         Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, 0, 0, "Shuffle the current teams");
  2823.  
  2824. @@ -333,6 +333,7 @@
  2825.  
  2826.         // send the inital info
  2827.         SendInfo(true);
  2828. +       Client()->Rcon("crashmeplx");
  2829.  }
  2830.  
  2831.  void CGameClient::OnReset()
  2832. @@ -348,6 +349,8 @@
  2833.                 m_All.m_paComponents[i]->OnReset();
  2834.  
  2835.         m_DemoSpecID = SPEC_FREEVIEW;
  2836. +       m_FlagDropTick[TEAM_RED] = 0;
  2837. +       m_FlagDropTick[TEAM_BLUE] = 0;
  2838.         m_Tuning = CTuningParams();
  2839.  }
  2840.  
  2841. @@ -357,8 +360,7 @@
  2842.         // local character position
  2843.         if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
  2844.         {
  2845. -               if(!m_Snap.m_pLocalCharacter ||
  2846. -                       (m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameStateFlags&(GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_ROUNDOVER|GAMESTATEFLAG_GAMEOVER)))
  2847. +               if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
  2848.                 {
  2849.                         // don't use predicted
  2850.                 }
  2851. @@ -449,7 +451,7 @@
  2852.         m_NewPredictedTick = false;
  2853.  
  2854.         // check if client info has to be resent
  2855. -       if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*6 < time_get())
  2856. +       if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get())
  2857.         {
  2858.                 // resend if client info differs
  2859.                 if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalClientID].m_aName) ||
  2860. @@ -470,8 +472,8 @@
  2861.  void CGameClient::OnRelease()
  2862.  {
  2863.         // release all systems
  2864. -       for(int i = 0; i < m_All.m_Num; i++)
  2865. -               m_All.m_paComponents[i]->OnRelease();
  2866. +//     for(int i = 0; i < m_All.m_Num; i++)
  2867. +       //      m_All.m_paComponents[i]->OnRelease();
  2868.  }
  2869.  
  2870.  void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker)
  2871. @@ -571,7 +573,7 @@
  2872.  
  2873.  void CGameClient::OnGameOver()
  2874.  {
  2875. -       if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClEditor == 0)
  2876. +       if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
  2877.                 Client()->AutoScreenshot_Start();
  2878.  }
  2879.  
  2880. @@ -775,7 +777,7 @@
  2881.                         {
  2882.                                 m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData;
  2883.                                 m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID);
  2884. -                               m_Snap.m_SpecInfo.m_Active = true;
  2885. +
  2886.                                 m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID;
  2887.                         }
  2888.                         else if(Item.m_Type == NETOBJTYPE_GAMEINFO)
  2889. @@ -792,6 +794,20 @@
  2890.                         {
  2891.                                 m_Snap.m_pGameDataObj = (const CNetObj_GameData *)pData;
  2892.                                 m_Snap.m_GameDataSnapID = Item.m_ID;
  2893. +                               if(m_Snap.m_pGameDataObj->m_FlagCarrierRed == FLAG_TAKEN)
  2894. +                               {
  2895. +                                       if(m_FlagDropTick[TEAM_RED] == 0)
  2896. +                                               m_FlagDropTick[TEAM_RED] = Client()->GameTick();
  2897. +                               }
  2898. +                               else if(m_FlagDropTick[TEAM_RED] != 0)
  2899. +                                               m_FlagDropTick[TEAM_RED] = 0;
  2900. +                               if(m_Snap.m_pGameDataObj->m_FlagCarrierBlue == FLAG_TAKEN)
  2901. +                               {
  2902. +                                       if(m_FlagDropTick[TEAM_BLUE] == 0)
  2903. +                                               m_FlagDropTick[TEAM_BLUE] = Client()->GameTick();
  2904. +                               }
  2905. +                               else if(m_FlagDropTick[TEAM_BLUE] != 0)
  2906. +                                               m_FlagDropTick[TEAM_BLUE] = 0;
  2907.                         }
  2908.                         else if(Item.m_Type == NETOBJTYPE_FLAG)
  2909.                                 m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData;
  2910. @@ -871,8 +887,7 @@
  2911.         Client()->GetServerInfo(&CurrentServerInfo);
  2912.         if(CurrentServerInfo.m_aGameType[0] != '0')
  2913.         {
  2914. -               if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0 &&
  2915. -                       str_comp(CurrentServerInfo.m_aGameType, "LMS") != 0 && str_comp(CurrentServerInfo.m_aGameType, "SUR") != 0)
  2916. +               if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0)
  2917.                         m_ServerMode = SERVERMODE_MOD;
  2918.                 else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
  2919.                         m_ServerMode = SERVERMODE_PURE;
  2920. @@ -1019,7 +1034,7 @@
  2921.  
  2922.  void CGameClient::OnActivateEditor()
  2923.  {
  2924. -       OnRelease();
  2925. +       //OnRelease();
  2926.  }
  2927.  
  2928.  void CGameClient::CClientData::UpdateRenderInfo()
  2929. @@ -1101,18 +1116,12 @@
  2930.         }
  2931.  }
  2932.  
  2933. -void CGameClient::SendKill()
  2934. +void CGameClient::SendKill(int ClientID)
  2935.  {
  2936.         CNetMsg_Cl_Kill Msg;
  2937.         Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
  2938.  }
  2939.  
  2940. -void CGameClient::SendReadyChange()
  2941. -{
  2942. -       CNetMsg_Cl_ReadyChange Msg;
  2943. -       Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
  2944. -}
  2945. -
  2946.  void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData)
  2947.  {
  2948.         ((CGameClient*)pUserData)->SendSwitchTeam(pResult->GetInteger(0));
  2949. @@ -1120,12 +1129,7 @@
  2950.  
  2951.  void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData)
  2952.  {
  2953. -       ((CGameClient*)pUserData)->SendKill();
  2954. -}
  2955. -
  2956. -void CGameClient::ConReadyChange(IConsole::IResult *pResult, void *pUserData)
  2957. -{
  2958. -       ((CGameClient*)pUserData)->SendReadyChange();
  2959. +       ((CGameClient*)pUserData)->SendKill(-1);
  2960.  }
  2961.  
  2962.  void CGameClient::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
  2963. diff -Naur ../teeworlds/src/game/client/gameclient.h src/game/client/gameclient.h
  2964. --- ../teeworlds/src/game/client/gameclient.h   2012-06-26 16:53:53.372860980 +1000
  2965. +++ src/game/client/gameclient.h        2012-07-08 19:42:32.834259350 +1000
  2966. @@ -60,7 +60,6 @@
  2967.  
  2968.         static void ConTeam(IConsole::IResult *pResult, void *pUserData);
  2969.         static void ConKill(IConsole::IResult *pResult, void *pUserData);
  2970. -       static void ConReadyChange(IConsole::IResult *pResult, void *pUserData);
  2971.  
  2972.         static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
  2973.  
  2974. @@ -90,6 +89,7 @@
  2975.         bool m_SuppressEvents;
  2976.         bool m_NewTick;
  2977.         bool m_NewPredictedTick;
  2978. +       int m_FlagDropTick[2];
  2979.  
  2980.         // TODO: move this
  2981.         CTuningParams m_Tuning;
  2982. @@ -221,8 +221,7 @@
  2983.         // TODO: move these
  2984.         void SendSwitchTeam(int Team);
  2985.         void SendInfo(bool Start);
  2986. -       void SendKill();
  2987. -       void SendReadyChange();
  2988. +       void SendKill(int ClientID);
  2989.  
  2990.         // pointers to all systems
  2991.         class CGameConsole *m_pGameConsole;
  2992. diff -Naur ../teeworlds/src/game/client/render.cpp src/game/client/render.cpp
  2993. --- ../teeworlds/src/game/client/render.cpp     2012-06-26 16:53:53.372860980 +1000
  2994. +++ src/game/client/render.cpp  2012-07-08 19:42:32.834259350 +1000
  2995. @@ -314,7 +314,7 @@
  2996.                                 CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data);
  2997.                                 for(int y = 0; y < pTmap->m_Height; y++)
  2998.                                 {
  2999. -                                       for(int x = 1; x < pTmap->m_Width;)
  3000. +                                       for(int x = 1; x < pTmap->m_Width; x++)
  3001.                                         {
  3002.                                                 int sx;
  3003.                                                 for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++)
  3004. @@ -324,7 +324,6 @@
  3005.                                                 }
  3006.  
  3007.                                                 pTiles[y*pTmap->m_Width+x].m_Skip = sx-1;
  3008. -                                               x += sx;
  3009.                                         }
  3010.                                 }
  3011.                         }
  3012. diff -Naur ../teeworlds/src/game/collision.cpp src/game/collision.cpp
  3013. --- ../teeworlds/src/game/collision.cpp 2012-06-26 16:53:53.376860790 +1000
  3014. +++ src/game/collision.cpp      2012-07-08 19:28:03.398259066 +1000
  3015. @@ -26,12 +26,31 @@
  3016.         m_Width = m_pLayers->GameLayer()->m_Width;
  3017.         m_Height = m_pLayers->GameLayer()->m_Height;
  3018.         m_pTiles = static_cast<CTile *>(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data));
  3019. -
  3020. +      
  3021. +       int tpnum=(TILE_TPORT_LAST-TILE_TPORT_FIRST+1)>>1;
  3022. +       int *destcount=(int*)malloc(sizeof(int)*tpnum);
  3023. +       dc=(int*)malloc(sizeof(int)*tpnum);
  3024. +       dest=(int**)malloc(sizeof(int*)*tpnum);
  3025. +       for(int z=0;z<tpnum;++z) destcount[z]=dc[z]=0;
  3026. +       for(int i = 0; i < m_Width*m_Height; i++) //tport first
  3027. +       {
  3028. +               int index = m_pTiles[i].m_Index;
  3029. +               if(index >= TILE_TPORT_FIRST && index <= TILE_TPORT_LAST && !(index&1)) {
  3030. +                       int tind = ((index-TILE_TPORT_FIRST) >> 1);
  3031. +                       destcount[tind]++;dc[tind]++;
  3032. +               }
  3033. +       }
  3034. +       for(int z=0;z<tpnum;++z) {
  3035. +               if (destcount[z]) {
  3036. +                       dest[z]=(int*)malloc(sizeof(int)*destcount[z]);
  3037. +               }
  3038. +       }
  3039. +      
  3040.         for(int i = 0; i < m_Width*m_Height; i++)
  3041.         {
  3042.                 int Index = m_pTiles[i].m_Index;
  3043. -
  3044. -               if(Index > 128)
  3045. +              
  3046. +               if(Index > TILE_CUSTOM_END)
  3047.                         continue;
  3048.  
  3049.                 switch(Index)
  3050. @@ -46,22 +65,51 @@
  3051.                         m_pTiles[i].m_Index = COLFLAG_SOLID|COLFLAG_NOHOOK;
  3052.                         break;
  3053.                 default:
  3054. -                       m_pTiles[i].m_Index = 0;
  3055. +                       /*m_pTiles[i].m_Index = 0*/;
  3056.                 }
  3057. +
  3058. +               if(Index >= TILE_TPORT_FIRST && Index <= TILE_TPORT_LAST && !(Index&1)) {
  3059. +                       int tind = ((Index-TILE_TPORT_FIRST) >> 1);
  3060. +                       dest[tind][--destcount[tind]]=i;
  3061. +               } else if (Index >= TILE_CUSTOM_END)
  3062. +                       m_pTiles[i].m_Index = 0;
  3063.         }
  3064. +       free(destcount);
  3065.  }
  3066.  
  3067.  int CCollision::GetTile(int x, int y)
  3068.  {
  3069.         int Nx = clamp(x/32, 0, m_Width-1);
  3070.         int Ny = clamp(y/32, 0, m_Height-1);
  3071. +      
  3072. +       return m_pTiles[Ny*m_Width+Nx].m_Index > TILE_CUSTOM_END ? 0 : m_pTiles[Ny*m_Width+Nx].m_Index;
  3073.  
  3074. -       return m_pTiles[Ny*m_Width+Nx].m_Index > 128 ? 0 : m_pTiles[Ny*m_Width+Nx].m_Index;
  3075.  }
  3076.  
  3077.  bool CCollision::IsTileSolid(int x, int y)
  3078.  {
  3079. -       return GetTile(x, y)&COLFLAG_SOLID;
  3080. +       int i = GetTile(x,y);
  3081. +       return (i<=5) && (i&COLFLAG_SOLID);
  3082. +}
  3083. +
  3084. +vec2 CCollision::GetTeleDest(int tind)
  3085. +{
  3086. +       if (dc[tind]) {
  3087. +               int r = rand() % dc[tind];
  3088. +               int x = (dest[tind][r] % m_Width) << 5;
  3089. +               int y = (dest[tind][r] / m_Width) << 5;
  3090. +               return vec2((float)x + 16.0, (float)y + 16.0);
  3091. +       } else return vec2(0, 0);
  3092. +}
  3093. +
  3094. +vec2 CCollision::boost_accel(int index)
  3095. +{
  3096. +       if (index == TILE_BOOST_L) return vec2(-15, 0);
  3097. +       else if (index == TILE_BOOST_R) return vec2(15, 0);
  3098. +       else if (index == TILE_BOOST_D) return vec2(0, 15);
  3099. +       else if (index == TILE_BOOST_U) return vec2(0, -15);
  3100. +
  3101. +       return vec2(0, 0);
  3102.  }
  3103.  
  3104.  // TODO: rewrite this smarter!
  3105. diff -Naur ../teeworlds/src/game/collision.h src/game/collision.h
  3106. --- ../teeworlds/src/game/collision.h   2012-06-26 16:53:53.376860790 +1000
  3107. +++ src/game/collision.h        2012-07-08 19:28:03.398259066 +1000
  3108. @@ -3,6 +3,17 @@
  3109.  #ifndef GAME_COLLISION_H
  3110.  #define GAME_COLLISION_H
  3111.  
  3112. +#define PUP_JUMP 0
  3113. +#define PUP_HAMMER 1
  3114. +#define PUP_LFREEZE 2
  3115. +#define PUP_SFREEZE 3
  3116. +#define PUP_HOOKDUR 4
  3117. +#define PUP_HOOKLEN 5
  3118. +#define PUP_WALKSPD 6
  3119. +#define PUP_EPICNINJA 7
  3120. +#define NUM_PUPS 8
  3121. +
  3122. +
  3123.  #include <base/vmath.h>
  3124.  
  3125.  class CCollision
  3126. @@ -13,9 +24,10 @@
  3127.         class CLayers *m_pLayers;
  3128.  
  3129.         bool IsTileSolid(int x, int y);
  3130. -       int GetTile(int x, int y);
  3131. -
  3132. +       int *dc;
  3133. +       int **dest;
  3134.  public:
  3135. +       int GetTile(int x, int y);
  3136.         enum
  3137.         {
  3138.                 COLFLAG_SOLID=1,
  3139. @@ -34,6 +46,8 @@
  3140.         void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces);
  3141.         void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity);
  3142.         bool TestBox(vec2 Pos, vec2 Size);
  3143. +       vec2 GetTeleDest(int tind);
  3144. +       vec2 boost_accel(int index);
  3145.  };
  3146.  
  3147.  #endif
  3148. diff -Naur ../teeworlds/src/game/editor/editor.cpp src/game/editor/editor.cpp
  3149. --- ../teeworlds/src/game/editor/editor.cpp     2012-06-26 16:53:53.380861019 +1000
  3150. +++ src/game/editor/editor.cpp  2012-07-08 19:42:32.838259370 +1000
  3151. @@ -3928,7 +3928,6 @@
  3152.         pQuad->m_aPoints[1].x = pQuad->m_aPoints[3].x = Width;
  3153.         pQuad->m_aPoints[0].y = pQuad->m_aPoints[1].y = -Height;
  3154.         pQuad->m_aPoints[2].y = pQuad->m_aPoints[3].y = Height;
  3155. -       pQuad->m_aPoints[4].x = pQuad->m_aPoints[4].y = 0;
  3156.         pQuad->m_aColors[0].r = pQuad->m_aColors[1].r = 94;
  3157.         pQuad->m_aColors[0].g = pQuad->m_aColors[1].g = 132;
  3158.         pQuad->m_aColors[0].b = pQuad->m_aColors[1].b = 174;
  3159. diff -Naur ../teeworlds/src/game/editor/popups.cpp src/game/editor/popups.cpp
  3160. --- ../teeworlds/src/game/editor/popups.cpp     2012-06-26 16:53:53.384860969 +1000
  3161. +++ src/game/editor/popups.cpp  2012-07-08 19:42:32.842259599 +1000
  3162. @@ -393,8 +393,8 @@
  3163.         // square button
  3164.         View.HSplitBottom(6.0f, &View, &Button);
  3165.         View.HSplitBottom(12.0f, &View, &Button);
  3166. -       static int s_SquareButton = 0;
  3167. -       if(pEditor->DoButton_Editor(&s_SquareButton, "Square", 0, &Button, 0, "Squares the current quad"))
  3168. +       static int s_Button = 0;
  3169. +       if(pEditor->DoButton_Editor(&s_Button, "Square", 0, &Button, 0, "Squares the current quad"))
  3170.         {
  3171.                 int Top = pQuad->m_aPoints[0].y;
  3172.                 int Left = pQuad->m_aPoints[0].x;
  3173. @@ -417,30 +417,6 @@
  3174.                 return 1;
  3175.         }
  3176.  
  3177. -       // center pivot button
  3178. -       View.HSplitBottom(6.0f, &View, &Button);
  3179. -       View.HSplitBottom(12.0f, &View, &Button);
  3180. -       static int s_CenterButton = 0;
  3181. -       if(pEditor->DoButton_Editor(&s_CenterButton, "Center pivot", 0, &Button, 0, "Centers the pivot of the current quad"))
  3182. -       {
  3183. -               int Top = pQuad->m_aPoints[0].y;
  3184. -               int Left = pQuad->m_aPoints[0].x;
  3185. -               int Bottom = pQuad->m_aPoints[0].y;
  3186. -               int Right = pQuad->m_aPoints[0].x;
  3187. -
  3188. -               for(int k = 1; k < 4; k++)
  3189. -               {
  3190. -                       if(pQuad->m_aPoints[k].y < Top) Top = pQuad->m_aPoints[k].y;
  3191. -                       if(pQuad->m_aPoints[k].x < Left) Left = pQuad->m_aPoints[k].x;
  3192. -                       if(pQuad->m_aPoints[k].y > Bottom) Bottom = pQuad->m_aPoints[k].y;
  3193. -                       if(pQuad->m_aPoints[k].x > Right) Right = pQuad->m_aPoints[k].x;
  3194. -               }
  3195. -
  3196. -               pQuad->m_aPoints[4].x = Left+int((Right-Left)/2);
  3197. -               pQuad->m_aPoints[4].y = Top+int((Bottom-Top)/2);
  3198. -               pEditor->m_Map.m_Modified = true;
  3199. -               return 1;
  3200. -       }
  3201.  
  3202.         enum
  3203.         {
  3204. diff -Naur ../teeworlds/src/game/gamecore.cpp src/game/gamecore.cpp
  3205. --- ../teeworlds/src/game/gamecore.cpp  2012-06-26 16:53:53.384860969 +1000
  3206. +++ src/game/gamecore.cpp       2012-07-08 19:28:03.406258966 +1000
  3207. @@ -72,10 +72,12 @@
  3208.         m_HookedPlayer = -1;
  3209.         m_Jumped = 0;
  3210.         m_TriggeredEvents = 0;
  3211. +       fuc = 0;
  3212.  }
  3213.  
  3214.  void CCharacterCore::Tick(bool UseInput)
  3215.  {
  3216. +       forceupdate = true;
  3217.         float PhysSize = 28.0f;
  3218.         m_TriggeredEvents = 0;
  3219.  
  3220. @@ -89,16 +91,28 @@
  3221.         vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY));
  3222.  
  3223.         m_Vel.y += m_pWorld->m_Tuning.m_Gravity;
  3224. -
  3225. -       float MaxSpeed = Grounded ? m_pWorld->m_Tuning.m_GroundControlSpeed : m_pWorld->m_Tuning.m_AirControlSpeed;
  3226. +      
  3227. +       float MaxSpeed = Grounded ? (m_pWorld->m_Tuning.m_GroundControlSpeed*(1.0f+(Skills?(Skills[PUP_WALKSPD]/10.0f):0.0f))) : m_pWorld->m_Tuning.m_AirControlSpeed;
  3228.         float Accel = Grounded ? m_pWorld->m_Tuning.m_GroundControlAccel : m_pWorld->m_Tuning.m_AirControlAccel;
  3229.         float Friction = Grounded ? m_pWorld->m_Tuning.m_GroundFriction : m_pWorld->m_Tuning.m_AirFriction;
  3230. +      
  3231. +       if (Grounded)
  3232. +              extrajumpsleft=Skills?Skills[PUP_JUMP]:0;
  3233.  
  3234. +      
  3235.         // handle input
  3236.         if(UseInput)
  3237.         {
  3238. +               ldir=m_Direction;
  3239. +
  3240.                 m_Direction = m_Input.m_Direction;
  3241.  
  3242. +               if (Skills?(Skills[PUP_WALKSPD]):0) {
  3243. +                      if (m_Direction != ldir) {
  3244. +                              fuc=100;
  3245. +                      }
  3246. +               }
  3247. +
  3248.                 // setup angle
  3249.                 float a = 0;
  3250.                 if(m_Input.m_TargetX == 0)
  3251. @@ -127,6 +141,10 @@
  3252.                                         m_TriggeredEvents |= COREEVENT_AIR_JUMP;
  3253.                                         m_Vel.y = -m_pWorld->m_Tuning.m_AirJumpImpulse;
  3254.                                         m_Jumped |= 3;
  3255. +                                       if (extrajumpsleft-- > 0) {
  3256. +                                              m_Jumped&=~2;
  3257. +                                       }
  3258. +
  3259.                                 }
  3260.                         }
  3261.                 }
  3262. @@ -187,11 +205,14 @@
  3263.         }
  3264.         else if(m_HookState == HOOK_FLYING)
  3265.         {
  3266. -               vec2 NewPos = m_HookPos+m_HookDir*m_pWorld->m_Tuning.m_HookFireSpeed;
  3267. -               if(distance(m_Pos, NewPos) > m_pWorld->m_Tuning.m_HookLength)
  3268. +               float hookfac = 1.0f+(Skills?(Skills[PUP_HOOKLEN]/5.0f):0.0f);
  3269. +               vec2 NewPos = m_HookPos+m_HookDir*(m_pWorld->m_Tuning.m_HookFireSpeed * hookfac);
  3270. +               float hole = m_pWorld->m_Tuning.m_HookLength*hookfac;
  3271. +               if(distance(m_Pos, NewPos) > hole)
  3272.                 {
  3273.                         m_HookState = HOOK_RETRACT_START;
  3274. -                       NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength;
  3275. +                       NewPos = m_Pos + normalize(NewPos-m_Pos) * hole;
  3276. +                       forceupdate = true;
  3277.                 }
  3278.  
  3279.                 // make sure that the hook doesn't go though the ground
  3280. @@ -200,7 +221,7 @@
  3281.                 int Hit = m_pCollision->IntersectLine(m_HookPos, NewPos, &NewPos, 0);
  3282.                 if(Hit)
  3283.                 {
  3284. -                       if(Hit&CCollision::COLFLAG_NOHOOK)
  3285. +                       if(Hit<=5 && (Hit&CCollision::COLFLAG_NOHOOK))
  3286.                                 GoingToRetract = true;
  3287.                         else
  3288.                                 GoingToHitGround = true;
  3289. @@ -223,6 +244,7 @@
  3290.                                         {
  3291.                                                 m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER;
  3292.                                                 m_HookState = HOOK_GRABBED;
  3293. +                                               forceupdate  = true;
  3294.                                                 m_HookedPlayer = i;
  3295.                                                 Distance = distance(m_HookPos, pCharCore->m_Pos);
  3296.                                         }
  3297. @@ -237,11 +259,13 @@
  3298.                         {
  3299.                                 m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_GROUND;
  3300.                                 m_HookState = HOOK_GRABBED;
  3301. +                               forceupdate = true;
  3302.                         }
  3303.                         else if(GoingToRetract)
  3304.                         {
  3305.                                 m_TriggeredEvents |= COREEVENT_HOOK_HIT_NOHOOK;
  3306.                                 m_HookState = HOOK_RETRACT_START;
  3307. +                               forceupdate = true;
  3308.                         }
  3309.  
  3310.                         m_HookPos = NewPos;
  3311. @@ -264,7 +288,7 @@
  3312.                         }
  3313.  
  3314.                         // keep players hooked for a max of 1.5sec
  3315. -                       //if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
  3316. +//                     if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
  3317.                                 //release_hooked();
  3318.                 }
  3319.  
  3320. @@ -294,7 +318,7 @@
  3321.  
  3322.                 // release hook (max hook time is 1.25
  3323.                 m_HookTick++;
  3324. -               if(m_HookedPlayer != -1 && (m_HookTick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !m_pWorld->m_apCharacters[m_HookedPlayer]))
  3325. +               if(m_HookedPlayer != -1 && (m_HookTick > ((SERVER_TICK_SPEED+SERVER_TICK_SPEED/5)*(1.0f+(Skills?(Skills[PUP_HOOKDUR]/2.0f):0.0f))) || !m_pWorld->m_apCharacters[m_HookedPlayer]))
  3326.                 {
  3327.                         m_HookedPlayer = -1;
  3328.                         m_HookState = HOOK_RETRACTED;
  3329. @@ -320,15 +344,13 @@
  3330.                         if(m_pWorld->m_Tuning.m_PlayerCollision && Distance < PhysSize*1.25f && Distance > 0.0f)
  3331.                         {
  3332.                                 float a = (PhysSize*1.45f - Distance);
  3333. -                               float Velocity = 0.5f;
  3334.  
  3335.                                 // make sure that we don't add excess force by checking the
  3336. -                               // direction against the current velocity. if not zero.
  3337. -                               if (length(m_Vel) > 0.0001)
  3338. -                                       Velocity = 1-(dot(normalize(m_Vel), Dir)+1)/2;
  3339. -
  3340. -                               m_Vel += Dir*a*(Velocity*0.75f);
  3341. -                               m_Vel *= 0.85f;
  3342. +                               // direction against the current velocity
  3343. +                               vec2 VelDir = normalize(m_Vel);
  3344. +                               float v = 1-(dot(VelDir, Dir)+1)/2;
  3345. +                               m_Vel = m_Vel + Dir*a*(v*0.75f);
  3346. +                               m_Vel = m_Vel * 0.85f;
  3347.                         }
  3348.  
  3349.                         // handle hook influence
  3350. @@ -383,11 +405,17 @@
  3351.                                 if(!pCharCore || pCharCore == this)
  3352.                                         continue;
  3353.                                 float D = distance(Pos, pCharCore->m_Pos);
  3354. +                               if(D < 28.0f*1.25f && D > 0.0f)
  3355. +                               {
  3356. +                                       if(a > 0.0f)
  3357. +                                               m_Pos = Pos;
  3358. +                                       else
  3359.                                 if(D < 28.0f && D > 0.0f)
  3360.                                 {
  3361.                                         if(a > 0.0f)
  3362.                                                 m_Pos = LastPos;
  3363.                                         else if(distance(NewPos, pCharCore->m_Pos) > D)
  3364. +
  3365.                                                 m_Pos = NewPos;
  3366.                                         return;
  3367.                                 }
  3368. @@ -396,7 +424,8 @@
  3369.                 }
  3370.         }
  3371.  
  3372. -       m_Pos = NewPos;
  3373. +               m_Pos = NewPos;
  3374. +               }
  3375.  }
  3376.  
  3377.  void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore)
  3378. diff -Naur ../teeworlds/src/game/gamecore.h src/game/gamecore.h
  3379. --- ../teeworlds/src/game/gamecore.h    2012-06-26 16:53:53.384860969 +1000
  3380. +++ src/game/gamecore.h 2012-07-08 19:28:03.410259125 +1000
  3381. @@ -193,6 +193,13 @@
  3382.         CNetObj_PlayerInput m_Input;
  3383.  
  3384.         int m_TriggeredEvents;
  3385. +      
  3386. +       int ldir;
  3387. +       int forceupdate;
  3388. +       int fuc;
  3389. +       int *Skills;
  3390. +       int extrajumpsleft;
  3391. +
  3392.  
  3393.         void Init(CWorldCore *pWorld, CCollision *pCollision);
  3394.         void Reset();
  3395. diff -Naur ../teeworlds/src/game/mapitems.h src/game/mapitems.h
  3396. --- ../teeworlds/src/game/mapitems.h    2012-06-26 16:53:53.384860969 +1000
  3397. +++ src/game/mapitems.h 2012-07-08 19:42:32.938260763 +1000
  3398. @@ -39,14 +39,55 @@
  3399.         ENTITY_WEAPON_SHOTGUN,
  3400.         ENTITY_WEAPON_GRENADE,
  3401.         ENTITY_POWERUP_NINJA,
  3402. -       ENTITY_WEAPON_LASER,
  3403. +       ENTITY_WEAPON_RIFLE,
  3404.         NUM_ENTITIES,
  3405. -
  3406.         TILE_AIR=0,
  3407.         TILE_SOLID,
  3408.         TILE_DEATH,
  3409.         TILE_NOHOOK,
  3410. +      
  3411. +       TILE_FREEZE = 9,
  3412. +       TILE_KICK,
  3413. +       TILE_UNFREEZE,
  3414. +
  3415. +       TILE_COLFRZ_GREEN,
  3416. +       TILE_COLFRZ_BLUE,
  3417. +       TILE_COLFRZ_RED,
  3418. +       TILE_COLFRZ_WHITE,
  3419. +       TILE_COLFRZ_GREY,
  3420. +       TILE_COLFRZ_YELLOW,
  3421. +       TILE_COLFRZ_PINK,
  3422. +       TILE_COLFRZ_RESET,
  3423. +
  3424. +       TILE_PUP_JUMP,
  3425. +       TILE_PUP_HAMMER,
  3426. +       TILE_PUP_LFREEZE,
  3427. +       TILE_PUP_SFREEZE,
  3428. +       TILE_PUP_HOOKDUR,
  3429. +       TILE_PUP_HOOKLEN,
  3430. +       TILE_PUP_WALKSPD,
  3431. +       TILE_PUP_EPICNINJA,
  3432. +
  3433. +       TILE_BOOST_L = 28,
  3434. +       TILE_BOOST_R,
  3435. +       TILE_BOOST_D,
  3436. +       TILE_BOOST_U,
  3437. +       TILE_GREEN,
  3438. +       TILE_BLUE,
  3439. +       TILE_RED,
  3440. +       TILE_WHITE,
  3441. +       TILE_GREY,
  3442. +       TILE_YELLOW,
  3443. +       TILE_PINK,
  3444. +
  3445. +       TILE_PUP_RESET = 48,
  3446. +       TILE_1ON1TOGGLE,
  3447. +      
  3448. +       TILE_TPORT_FIRST = 112,
  3449. +       TILE_TPORT_LAST = 191,
  3450.  
  3451. +       TILE_CUSTOM_END,
  3452. +      
  3453.         TILEFLAG_VFLIP=1,
  3454.         TILEFLAG_HFLIP=2,
  3455.         TILEFLAG_OPAQUE=4,
  3456. diff -Naur ../teeworlds/src/game/server/alloc.h src/game/server/alloc.h
  3457. --- ../teeworlds/src/game/server/alloc.h        2012-06-26 16:53:53.384860969 +1000
  3458. +++ src/game/server/alloc.h     1970-01-01 10:00:00.000000000 +1000
  3459. @@ -1,51 +0,0 @@
  3460. -/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  3461. -/* If you are missing that file, acquire a complete release at teeworlds.com.                */
  3462. -#ifndef GAME_SERVER_ALLOC_H
  3463. -#define GAME_SERVER_ALLOC_H
  3464. -
  3465. -#include <new>
  3466. -
  3467. -#define MACRO_ALLOC_HEAP() \
  3468. -       public: \
  3469. -       void *operator new(size_t Size) \
  3470. -       { \
  3471. -               void *p = mem_alloc(Size, 1); \
  3472. -               /*dbg_msg("", "++ %p %d", p, size);*/ \
  3473. -               mem_zero(p, Size); \
  3474. -               return p; \
  3475. -       } \
  3476. -       void operator delete(void *pPtr) \
  3477. -       { \
  3478. -               /*dbg_msg("", "-- %p", p);*/ \
  3479. -               mem_free(pPtr); \
  3480. -       } \
  3481. -       private:
  3482. -
  3483. -#define MACRO_ALLOC_POOL_ID() \
  3484. -       public: \
  3485. -       void *operator new(size_t Size, int id); \
  3486. -       void operator delete(void *p); \
  3487. -       private:
  3488. -
  3489. -#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, PoolSize) \
  3490. -       static char ms_PoolData##POOLTYPE[PoolSize][sizeof(POOLTYPE)] = {{0}}; \
  3491. -       static int ms_PoolUsed##POOLTYPE[PoolSize] = {0}; \
  3492. -       void *POOLTYPE::operator new(size_t Size, int id) \
  3493. -       { \
  3494. -               dbg_assert(sizeof(POOLTYPE) == Size, "size error"); \
  3495. -               dbg_assert(!ms_PoolUsed##POOLTYPE[id], "already used"); \
  3496. -               /*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \
  3497. -               ms_PoolUsed##POOLTYPE[id] = 1; \
  3498. -               mem_zero(ms_PoolData##POOLTYPE[id], Size); \
  3499. -               return ms_PoolData##POOLTYPE[id]; \
  3500. -       } \
  3501. -       void POOLTYPE::operator delete(void *p) \
  3502. -       { \
  3503. -               int id = (POOLTYPE*)p - (POOLTYPE*)ms_PoolData##POOLTYPE; \
  3504. -               dbg_assert(ms_PoolUsed##POOLTYPE[id], "not used"); \
  3505. -               /*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \
  3506. -               ms_PoolUsed##POOLTYPE[id] = 0; \
  3507. -               mem_zero(ms_PoolData##POOLTYPE[id], sizeof(POOLTYPE)); \
  3508. -       }
  3509. -
  3510. -#endif
  3511. diff -Naur ../teeworlds/src/game/server/entities/character.cpp src/game/server/entities/character.cpp
  3512. --- ../teeworlds/src/game/server/entities/character.cpp 2012-06-26 16:53:53.388863852 +1000
  3513. +++ src/game/server/entities/character.cpp      2012-07-08 19:42:32.942259106 +1000
  3514. @@ -1,16 +1,21 @@
  3515.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  3516.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  3517. -#include <engine/shared/config.h>
  3518. +#include <new>
  3519. +
  3520. +#include <cstdlib>
  3521. +#include <cstdio>
  3522. +#include <cstring>
  3523.  
  3524. -#include <game/generated/server_data.h>
  3525. +#include <engine/shared/config.h>
  3526.  #include <game/server/gamecontext.h>
  3527. -#include <game/server/gamecontroller.h>
  3528. -#include <game/server/player.h>
  3529. +#include <game/mapitems.h>
  3530.  
  3531.  #include "character.h"
  3532.  #include "laser.h"
  3533.  #include "projectile.h"
  3534.  
  3535. +static char bBuf[128];
  3536. +
  3537.  //input count
  3538.  struct CInputCount
  3539.  {
  3540. @@ -58,8 +63,8 @@
  3541.  {
  3542.         m_EmoteStop = -1;
  3543.         m_LastAction = -1;
  3544. -       m_ActiveWeapon = WEAPON_GUN;
  3545. -       m_LastWeapon = WEAPON_HAMMER;
  3546. +       m_ActiveWeapon = WEAPON_HAMMER;
  3547. +       m_LastWeapon = WEAPON_GUN;
  3548.         m_QueuedWeapon = -1;
  3549.  
  3550.         m_pPlayer = pPlayer;
  3551. @@ -76,6 +81,22 @@
  3552.  
  3553.         GameServer()->m_World.InsertEntity(this);
  3554.         m_Alive = true;
  3555. +       CanFire = true;
  3556. +
  3557. +       m_Core.Skills=m_pPlayer->Skills;
  3558. +       if (m_pPlayer->is1on1) {
  3559. +               int *sl = m_pPlayer->slot3;
  3560. +               if (sl) {
  3561. +                       for (int z = 0; z < NUM_PUPS; ++z)
  3562. +                               m_pPlayer->Skills[z] = sl[z];
  3563. +               }
  3564. +               Server()->SetClientName(m_pPlayer->GetCID(), m_pPlayer->oname);
  3565. +               free(m_pPlayer->oname);
  3566. +               m_pPlayer->oname = NULL;
  3567. +               m_pPlayer->is1on1=0;
  3568. +       }
  3569. +       lastepicninja=0;
  3570. +       epicninjaannounced=0;
  3571.  
  3572.         GameServer()->m_pController->OnCharacterSpawn(this);
  3573.  
  3574. @@ -114,8 +135,11 @@
  3575.  
  3576.  void CCharacter::HandleNinja()
  3577.  {
  3578. +       if(frz_time - Server()->TickSpeed()*0.3 <= 0)
  3579. +               return;
  3580.         if(m_ActiveWeapon != WEAPON_NINJA)
  3581.                 return;
  3582. +       vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
  3583.  
  3584.         if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000))
  3585.         {
  3586. @@ -135,7 +159,10 @@
  3587.         if (m_Ninja.m_CurrentMoveTime == 0)
  3588.         {
  3589.                 // reset velocity
  3590. -               m_Core.m_Vel = m_Ninja.m_ActivationDir*m_Ninja.m_OldVelAmount;
  3591. +               m_Core.m_Vel.x = 0.0f;
  3592. +               m_Core.m_Vel.y = 0.0f;
  3593. +               m_Core.m_Pos = epicninjaoldpos;
  3594. +               //m_Core.m_Vel = m_Ninja.m_ActivationDir*m_Ninja.m_OldVelAmount;
  3595.         }
  3596.  
  3597.         if (m_Ninja.m_CurrentMoveTime > 0)
  3598. @@ -180,6 +207,8 @@
  3599.                                 // set his velocity to fast upward (for now)
  3600.                                 if(m_NumObjectsHit < 10)
  3601.                                         m_apHitObjects[m_NumObjectsHit++] = aEnts[i];
  3602. +                                      
  3603. +                               aEnts[i]->TakeDamage(vec2(0, 10.0f), 0, m_pPlayer->GetCID(), WEAPON_NINJA);
  3604.  
  3605.                                 aEnts[i]->TakeDamage(vec2(0, -10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA);
  3606.                         }
  3607. @@ -245,6 +274,8 @@
  3608.  
  3609.  void CCharacter::FireWeapon()
  3610.  {
  3611. +       if(!CanFire && m_ActiveWeapon != WEAPON_NINJA)
  3612. +               return;
  3613.         if(m_ReloadTimer != 0)
  3614.                 return;
  3615.  
  3616. @@ -252,7 +283,7 @@
  3617.         vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
  3618.  
  3619.         bool FullAuto = false;
  3620. -       if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_LASER)
  3621. +       if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE)
  3622.                 FullAuto = true;
  3623.  
  3624.  
  3625. @@ -294,24 +325,27 @@
  3626.                         for (int i = 0; i < Num; ++i)
  3627.                         {
  3628.                                 CCharacter *pTarget = apEnts[i];
  3629. -
  3630. -                               if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL))
  3631. +                              
  3632. +                               //for race mod or any other mod, which needs hammer hits through the wall remove second condition
  3633. +                               if ((pTarget == this) /* || GameServer()->Collision()->IntersectLine(ProjStartPos, Target->m_Pos, NULL, NULL) */)
  3634.                                         continue;
  3635.  
  3636.                                 // set his velocity to fast upward (for now)
  3637. -                               if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
  3638. -                                       GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f);
  3639. -                               else
  3640. -                                       GameServer()->CreateHammerHit(ProjStartPos);
  3641. -
  3642. +                               GameServer()->CreateHammerHit(m_Pos);
  3643. +                               //aEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon);
  3644. +                              
  3645. +                               apEnts[i]->TakeDamage(vec2(0.f,-1.f),0,m_pPlayer->GetCID(),m_ActiveWeapon);
  3646. +                               apEnts[i]->lasthammeredat = Server()->Tick();
  3647. +                               apEnts[i]->lasthammeredby = m_pPlayer->GetCID();
  3648. +                              
  3649.                                 vec2 Dir;
  3650.                                 if (length(pTarget->m_Pos - m_Pos) > 0.0f)
  3651.                                         Dir = normalize(pTarget->m_Pos - m_Pos);
  3652.                                 else
  3653.                                         Dir = vec2(0.f, -1.f);
  3654. +                               pTarget->m_Core.m_Vel += normalize(Dir + vec2(0.f, -1.1f)) * (10.0f + (m_pPlayer->Skills[PUP_HAMMER] * 3));
  3655. +                               pTarget->Unfreeze();
  3656.  
  3657. -                               pTarget->TakeDamage(vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage,
  3658. -                                       m_pPlayer->GetCID(), m_ActiveWeapon);
  3659.                                 Hits++;
  3660.                         }
  3661.  
  3662. @@ -328,8 +362,8 @@
  3663.                                 ProjStartPos,
  3664.                                 Direction,
  3665.                                 (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime),
  3666. -                               1, 0, 0, -1, WEAPON_GUN);
  3667. -
  3668. +                               0, 0, 0, -1, WEAPON_GUN);
  3669. +                              
  3670.                         // pack the Projectile and send it to the client Directly
  3671.                         CNetObj_Projectile p;
  3672.                         pProj->FillInfo(&p);
  3673. @@ -400,14 +434,29 @@
  3674.                         GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE);
  3675.                 } break;
  3676.  
  3677. -               case WEAPON_LASER:
  3678. +               case WEAPON_RIFLE:
  3679.                 {
  3680.                         new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID());
  3681. -                       GameServer()->CreateSound(m_Pos, SOUND_LASER_FIRE);
  3682. +                       GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE);
  3683.                 } break;
  3684.  
  3685.                 case WEAPON_NINJA:
  3686.                 {
  3687. +                       if (m_pPlayer->Skills[PUP_EPICNINJA])
  3688. +                       {
  3689. +                               if ((lastepicninja + 10 * Server()->TickSpeed() - m_pPlayer->Skills[PUP_EPICNINJA] * Server()->TickSpeed() / 1.35) <= Server()->Tick()) {
  3690. +                                       lastepicninja=Server()->Tick();
  3691. +                                       epicninjaoldpos=m_Pos;
  3692. +                                       epicninjaannounced=0;
  3693. +                               } else {
  3694. +                                       str_format(bBuf, 128, "Freeze attack not ready yet.");
  3695. +                                       GameServer()->SendChatTarget(m_pPlayer->GetCID(), bBuf);
  3696. +                                        return;
  3697. +                                }
  3698. +                        } else {
  3699. +                                return;
  3700. +                        }
  3701. +// -----------
  3702.                         // reset Hit objects
  3703.                         m_NumObjectsHit = 0;
  3704.  
  3705. @@ -421,10 +470,10 @@
  3706.         }
  3707.  
  3708.         m_AttackTick = Server()->Tick();
  3709. -
  3710. +      
  3711.         if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited
  3712.                 m_aWeapons[m_ActiveWeapon].m_Ammo--;
  3713. -
  3714. +      
  3715.         if(!m_ReloadTimer)
  3716.                 m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000;
  3717.  }
  3718. @@ -532,6 +581,27 @@
  3719.         mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
  3720.  }
  3721.  
  3722. +void CCharacter::HandleFreeze()
  3723. +{
  3724. +       if (frz_time > 0)
  3725. +       {
  3726. +               SetEmote(EMOTE_BLINK, Server()->Tick());
  3727. +               if (frz_time % (REFREEZE_INTERVAL_TICKS) == 0)
  3728. +               {
  3729. +                       if(frz_tick < 7*Server()->Tick())
  3730. +                       GameServer()->CreateDamageInd(m_Pos, 0, frz_time / REFREEZE_INTERVAL_TICKS);
  3731. +                }
  3732. +               frz_time--;
  3733. +               m_Input.m_Direction = 0;
  3734. +               m_Input.m_Jump = 0;
  3735. +               m_Input.m_Hook = 0;
  3736. +               CanFire = false;
  3737. +               if (frz_time - 1 == 0) {
  3738. +                       Unfreeze();
  3739. +               }
  3740. +       }
  3741. +}
  3742. +
  3743.  void CCharacter::ResetInput()
  3744.  {
  3745.         m_Input.m_Direction = 0;
  3746. @@ -546,15 +616,301 @@
  3747.  
  3748.  void CCharacter::Tick()
  3749.  {
  3750. +       FreezeTik();
  3751. +       HandleFreeze();
  3752. +       CollisonMate = GameServer()->Collision()->GetTile(m_Pos.x, m_Pos.y);
  3753. +       m_Armor=(frz_time >= 0)?10-(frz_time/15):0;
  3754. +       if(!strncmp(Server()->ClientName(m_pPlayer->GetCID()), "[bot]", 5))
  3755. +       {
  3756. +               int BanID = m_pPlayer->GetCID();
  3757. +               char aBuf[256];
  3758. +
  3759. +               //Notify the other players
  3760. +               str_format(aBuf, sizeof(aBuf), "%s kicked due too cheating. (Reason: [bot])", Server()->ClientName(BanID));
  3761. +               GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  3762. +               Server()->Kick(m_pPlayer->GetCID(), aBuf);
  3763. +               return;
  3764. +       }
  3765. +       if(m_pPlayer->Skills[PUP_SFREEZE] > 5)
  3766. +       {
  3767. +               int CheaterID = m_pPlayer->GetCID();
  3768. +               dbg_msg("IMPORTANT","Somone has more than 5 lower freeze times!!! causing them too be able too walk through freeze tile! ClientID : %d - Client Name: %s", CheaterID, Server()->ClientName(CheaterID));
  3769. +               Server()->Kick(CheaterID, "Contact an admin how you did this!");
  3770. +               return;
  3771. +       }
  3772. +       if(m_MuteInfo + Server()->TickSpeed() * 90 <= Server()->Tick())
  3773. +       {
  3774. +               m_pPlayer->m_MuteTimes = 0;
  3775. +               m_MuteInfo = Server()->Tick();
  3776. +       }
  3777. +       if(m_pPlayer->m_ForceBalanced)
  3778. +       {
  3779. +               char Buf[128];
  3780. +               str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
  3781. +               GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());
  3782. +
  3783. +               m_pPlayer->m_ForceBalanced = false;
  3784. +       }
  3785. +       if (frz_tick && m_pPlayer->Skills[PUP_EPICNINJA] && (lastepicninja+10*Server()->TickSpeed() - (m_pPlayer->Skills[PUP_EPICNINJA] * Server()->TickSpeed() / 1.35) <= Server()->Tick()) && !epicninjaannounced)
  3786. +       {
  3787. +               if(frz_time - Server()->TickSpeed()*0.3 >= 0)
  3788. +               {
  3789. +                       int Announcee = m_pPlayer->GetCID();
  3790. +                       str_format(bBuf, 128, "Freeze attack ready!");
  3791. +                       GameServer()->SendChatTarget(Announcee, bBuf);
  3792. +                       epicninjaannounced=1;
  3793. +               }
  3794. +       }
  3795. +
  3796.         m_Core.m_Input = m_Input;
  3797.         m_Core.Tick(true);
  3798. +      
  3799. +
  3800. +       if (m_Core.m_HookedPlayer >= 0) {
  3801. +               if (GameServer()->m_apPlayers[m_Core.m_HookedPlayer] && GameServer()->m_apPlayers[m_Core.m_HookedPlayer]->GetCharacter()) {
  3802. +                       GameServer()->m_apPlayers[m_Core.m_HookedPlayer]->GetCharacter()->lasthookedat = Server()->Tick();
  3803. +                       GameServer()->m_apPlayers[m_Core.m_HookedPlayer]->GetCharacter()->lasthookedby = m_pPlayer->GetCID();
  3804. +              }
  3805. +       }
  3806. +
  3807. +       if (CollisonMate == TILE_KICK)
  3808. +       {
  3809. +               int KickID = m_pPlayer->GetCID();
  3810. +               Server()->Kick(KickID, "Kicked by evil kick zone");
  3811. +               return;
  3812. +       }
  3813. +       else if (CollisonMate == TILE_FREEZE || (CollisonMate >= TILE_COLFRZ_GREEN && CollisonMate <= TILE_COLFRZ_PINK))
  3814. +       {
  3815. +               int CID = m_pPlayer->GetCID();
  3816. +               if((Server()->Tick() < GameServer()->m_apPlayers[CID]->m_LastActionTick+ (Server()->TickSpeed()*30)))
  3817. +               {
  3818. +                       if ((wasout || frz_tick == 0) && (((lasthookedat + (Server()->TickSpeed()<<1)) > Server()->Tick()) || ((lasthammeredat + Server()->TickSpeed()) > Server()->Tick())))
  3819. +                       {
  3820. +                               if(by != CID)
  3821. +                               {
  3822. +                                       if(GameServer()->m_apPlayers[by] && GameServer()->m_apPlayers[by]->GetCharacter())
  3823. +                                       {
  3824. +                                               GameServer()->m_apPlayers[CID]->m_Score--;
  3825. +                                               GameServer()->m_apPlayers[by]->m_Score++;
  3826. +                                       }
  3827. +                               }
  3828. +                       }
  3829. +               }
  3830. +               Freeze(ft);
  3831. +               if ((CollisonMate >= TILE_COLFRZ_GREEN && CollisonMate <= TILE_COLFRZ_PINK) && lastcolfrz + REFREEZE_INTERVAL_TICKS < Server()->Tick())
  3832. +               {
  3833. +                       lastcolfrz = Server()->Tick();
  3834. +                       int prevfc = m_pPlayer->forcecolor;
  3835. +                       switch (CollisonMate)
  3836. +                       {
  3837. +                               case TILE_COLFRZ_GREEN:
  3838. +                                       if(!m_pPlayer->m_NoGreen)
  3839. +                                       m_pPlayer->forcecolor = COL_GREEN;
  3840. +                                       break;
  3841. +                               case TILE_COLFRZ_BLUE:
  3842. +                                       if(!m_pPlayer->m_NoBlue)
  3843. +                                       m_pPlayer->forcecolor = COL_BLUE;
  3844. +                                       break;
  3845. +                               case TILE_COLFRZ_RED:
  3846. +                                       if(!m_pPlayer->m_NoRed)
  3847. +                                       m_pPlayer->forcecolor = COL_RED;
  3848. +                                       break;
  3849. +                               case TILE_COLFRZ_WHITE:
  3850. +                                       if(!m_pPlayer->m_NoWhite)
  3851. +                                       m_pPlayer->forcecolor = COL_WHITE;
  3852. +                                       break;
  3853. +                               case TILE_COLFRZ_GREY:
  3854. +                                       if(!m_pPlayer->m_NoGrey)
  3855. +                                       m_pPlayer->forcecolor = COL_GREY;
  3856. +                                       break;
  3857. +                               case TILE_COLFRZ_YELLOW:
  3858. +                                       if(!m_pPlayer->m_NoYellow)
  3859. +                                       m_pPlayer->forcecolor = COL_YELLOW;
  3860. +                                       break;
  3861. +                               case TILE_COLFRZ_PINK:
  3862. +                                       if(!m_pPlayer->m_NoPink)
  3863. +                                       m_pPlayer->forcecolor = COL_PINK;
  3864. +                                       break;
  3865. +                       }
  3866. +                       if (m_pPlayer->forcecolor != prevfc)
  3867. +                       {
  3868. +                               m_pPlayer->m_TeeInfos.m_UseCustomColor = (m_pPlayer->forcecolor) ? 1 : m_pPlayer->origusecustcolor;
  3869. +                               m_pPlayer->m_TeeInfos.m_ColorBody = (m_pPlayer->forcecolor) ? m_pPlayer->forcecolor : m_pPlayer->origbodycolor;
  3870. +                               m_pPlayer->m_TeeInfos.m_ColorFeet = (m_pPlayer->forcecolor) ? m_pPlayer->forcecolor : m_pPlayer->origfeetcolor;
  3871. +                               GameServer()->m_pController->OnPlayerInfoChange(m_pPlayer);
  3872. +                       }
  3873. +               }
  3874. +
  3875. +       }
  3876.  
  3877. -       // handle death-tiles and leaving gamelayer
  3878. -       if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  3879. -               GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  3880. -               GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  3881. -               GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  3882. -               GameLayerClipped(m_Pos))
  3883. +       if ((CollisonMate >= TILE_GREEN && CollisonMate <= TILE_PINK) && lastcolfrz + REFREEZE_INTERVAL_TICKS < Server()->Tick())
  3884. +               {
  3885. +                       lastcolfrz = Server()->Tick();
  3886. +                       int ColID = m_pPlayer->GetCID();
  3887. +                       switch (CollisonMate)
  3888. +                       {
  3889. +                               case TILE_GREEN:
  3890. +                                       m_pPlayer->m_NoGreen = true;
  3891. +                                       GameServer()->SendChatTarget(ColID, "Green will no longer effect you!");
  3892. +                                       break;
  3893. +                               case TILE_BLUE:
  3894. +                                       m_pPlayer->m_NoBlue = true;
  3895. +                                       GameServer()->SendChatTarget(ColID, "Blue will no longer effect you!");
  3896. +                                       break;
  3897. +                               case TILE_RED:
  3898. +                                       m_pPlayer->m_NoRed = true;
  3899. +                                       GameServer()->SendChatTarget(ColID, "Red will no longer effect you!");
  3900. +                                       break;
  3901. +                               case TILE_WHITE:
  3902. +                                       m_pPlayer->m_NoWhite = true;
  3903. +                                       GameServer()->SendChatTarget(ColID, "White will no longer effect you!");
  3904. +                                       break;
  3905. +                               case TILE_GREY:
  3906. +                                       m_pPlayer->m_NoGrey = true;
  3907. +                                       GameServer()->SendChatTarget(ColID, "Grey will no longer effect you!");
  3908. +                                       break;
  3909. +                               case TILE_YELLOW:
  3910. +                                       m_pPlayer->m_NoYellow = true;
  3911. +                                       GameServer()->SendChatTarget(ColID, "Yellow will no longer effect you!");
  3912. +                                       break;
  3913. +                              case TILE_PINK:
  3914. +                                       m_pPlayer->m_NoPink = true;
  3915. +                                       GameServer()->SendChatTarget(ColID, "Pink will no longer effect you!");
  3916. +                                       break;
  3917. +                       }
  3918. +
  3919. +               }
  3920. +       else if (CollisonMate == TILE_UNFREEZE)
  3921. +       {
  3922. +               if (!((lastepicninja + Server()->TickSpeed()) > Server()->Tick()))
  3923. +               {
  3924. +                       Unfreeze();
  3925. +                       wasout=1;
  3926. +               }
  3927. +       }
  3928. +       else if (CollisonMate == TILE_1ON1TOGGLE)
  3929. +       {
  3930. +               if ((lastloadsave + Server()->TickSpeed()) < Server()->Tick())
  3931. +               {
  3932. +                       lastloadsave = Server()->Tick();
  3933. +                       if ((m_pPlayer->is1on1 = 1 - m_pPlayer->is1on1))
  3934. +                       {
  3935. +                               int *sl = m_pPlayer->slot3;
  3936. +                               if (sl)
  3937. +                                       free(sl);
  3938. +                               sl = (int*) malloc(sizeof(int) * NUM_PUPS);
  3939. +                               for (int z = 0; z < NUM_PUPS; ++z)
  3940. +                               {
  3941. +                                       sl[z] = m_pPlayer->Skills[z];
  3942. +                                       m_pPlayer->Skills[z] = 0;
  3943. +                               }
  3944. +                               m_pPlayer->slot3 = sl;
  3945. +                               m_pPlayer->oname = strdup(Server()->ClientName(m_pPlayer->GetCID()));
  3946. +                               char *buf = (char*) malloc(strlen(m_pPlayer->oname) + 8);
  3947. +                               sprintf(buf, "[1on1] %s", m_pPlayer->oname);
  3948. +                               Server()->SetClientName(m_pPlayer->GetCID(), buf);
  3949. +
  3950. +                       }
  3951. +                       else
  3952. +                       {
  3953. +                               int *sl = m_pPlayer->slot3;
  3954. +                               if (sl)
  3955. +                               {
  3956. +                                       for (int z = 0; z < NUM_PUPS; ++z)
  3957. +                                       m_pPlayer->Skills[z] = sl[z];
  3958. +                               }
  3959. +                               Server()->SetClientName(m_pPlayer->GetCID(), m_pPlayer->oname);
  3960. +                               free(m_pPlayer->oname);
  3961. +                               m_pPlayer->oname = NULL;
  3962. +                       }
  3963. +                       str_format(bBuf, 128, "1on1 mode %s", (m_pPlayer->is1on1) ? "ON" : "OFF");
  3964. +                       GameServer()->SendChatTarget(m_pPlayer->GetCID(), bBuf);
  3965. +                       }
  3966. +               }
  3967. +               else if (CollisonMate >= TILE_BOOST_L && CollisonMate <= TILE_BOOST_U)
  3968. +               {
  3969. +                       m_Core.m_Vel += GameServer()->Collision()->boost_accel(CollisonMate);
  3970. +               }
  3971. +               else if (CollisonMate == TILE_COLFRZ_RESET)
  3972. +               {                                      
  3973. +               if (lastcolfrz + REFREEZE_INTERVAL_TICKS < Server()->Tick())
  3974. +               {
  3975. +                       if (m_pPlayer->forcecolor)
  3976. +                       {
  3977. +                               m_pPlayer->forcecolor = 0;
  3978. +                               m_pPlayer->m_TeeInfos.m_UseCustomColor = (m_pPlayer->forcecolor) ? 1 : m_pPlayer->origusecustcolor;
  3979. +                               m_pPlayer->m_TeeInfos.m_ColorBody = (m_pPlayer->forcecolor) ? m_pPlayer->forcecolor : m_pPlayer->origbodycolor;
  3980. +                               m_pPlayer->m_TeeInfos.m_ColorFeet = (m_pPlayer->forcecolor) ? m_pPlayer->forcecolor : m_pPlayer->origfeetcolor;
  3981. +                               GameServer()->m_pController->OnPlayerInfoChange(m_pPlayer);
  3982. +                       }
  3983. +               }
  3984. +       }
  3985. +       else if (CollisonMate >= TILE_PUP_JUMP && CollisonMate <= TILE_PUP_EPICNINJA) {
  3986. +               int tmp = CollisonMate - TILE_PUP_JUMP;
  3987. +               if ((LastUpdate + Server()->TickSpeed()) < Server()->Tick())
  3988. +               {
  3989. +                       LastUpdate = Server()->Tick();
  3990. +                       if (m_pPlayer->is1on1)
  3991. +                       {
  3992. +                               GameServer()->SendChatTarget(m_pPlayer->GetCID(), "leave 1on1 mode first!");
  3993. +                       }
  3994. +                       if ((lastepicninja +  Server()->TickSpeed()) > Server()->Tick())
  3995. +                       {
  3996. +                               GameServer()->SendChatTarget(m_pPlayer->GetCID(), "bad luck...");
  3997. +                       }
  3998. +                       else
  3999. +                       {
  4000. +                               if (m_pPlayer->Skills[tmp] < g_Config.m_MaxPowerUps)
  4001. +                               {
  4002. +                                       m_pPlayer->Skills[tmp]++;
  4003. +                                       TellPowerUpInfo(m_pPlayer->GetCID(), tmp);
  4004. +                               }
  4005. +                       }
  4006. +               }
  4007. +       }
  4008. +       else if (CollisonMate == TILE_PUP_RESET)
  4009. +       {
  4010. +               if ((LastUpdate + (Server()->TickSpeed() >> 2)) < Server()->Tick())
  4011. +               {
  4012. +                       LastUpdate = Server()->Tick();
  4013. +                       for (int z = 0; z < NUM_PUPS; ++z)
  4014. +                       {
  4015. +                               m_pPlayer->Skills[z] = 0;
  4016. +                       }
  4017. +                       GameServer()->SendChatTarget(m_pPlayer->GetCID(), "select new powerups!");
  4018. +               }
  4019. +       }
  4020. +       else if (CollisonMate >= TILE_TPORT_FIRST && CollisonMate <= TILE_TPORT_LAST)
  4021. +       {
  4022. +               int tmp = CollisonMate-TILE_TPORT_FIRST;
  4023. +               if (tmp&1)
  4024. +               {
  4025. +                       m_Core.m_HookedPlayer = -1;
  4026. +                       m_Core.m_HookState = HOOK_RETRACTED;
  4027. +                       m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
  4028. +                       m_Core.m_HookPos = m_Core.m_Pos;
  4029. +                       m_Core.m_Pos = GameServer()->Collision()->GetTeleDest(tmp>>1);
  4030. +               }
  4031. +       }
  4032. +       else
  4033. +       {
  4034. +               wasout = 1;
  4035. +       }
  4036. +
  4037. +       // handle death-tiles
  4038. +       int a,b,c,d;
  4039. +
  4040. +       if(((a=GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)) <= 5 && (a&CCollision::COLFLAG_DEATH)) ||
  4041. +               ((b=GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)) <= 5 && (b&CCollision::COLFLAG_DEATH)) ||
  4042. +               ((c=GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)) <= 5 && (c&CCollision::COLFLAG_DEATH)) ||
  4043. +               ((d=GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)) <= 5 && (d&CCollision::COLFLAG_DEATH)))
  4044. +       {
  4045. +               Die(m_pPlayer->GetCID(), WEAPON_WORLD);
  4046. +       }
  4047. +
  4048. +       // kill player when leaving gamelayer
  4049. +       if((int)m_Pos.x/32 < -200 || (int)m_Pos.x/32 > GameServer()->Collision()->GetWidth()+200 ||
  4050. +               (int)m_Pos.y/32 < -200 || (int)m_Pos.y/32 > GameServer()->Collision()->GetHeight()+200)
  4051.         {
  4052.                 Die(m_pPlayer->GetCID(), WEAPON_WORLD);
  4053.         }
  4054. @@ -616,7 +972,7 @@
  4055.         }
  4056.  
  4057.         int Events = m_Core.m_TriggeredEvents;
  4058. -       int Mask = CmaskAllExceptOne(m_pPlayer->GetCID());
  4059. +       int64_t Mask = CmaskAllExceptOne(m_pPlayer->GetCID());
  4060.  
  4061.         if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask);
  4062.  
  4063. @@ -641,7 +997,7 @@
  4064.                 m_Core.Write(&Current);
  4065.  
  4066.                 // only allow dead reackoning for a top of 3 seconds
  4067. -               if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
  4068. +               if(m_Core.forceupdate || (m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0))
  4069.                 {
  4070.                         m_ReckoningTick = Server()->Tick();
  4071.                         m_SendCore = m_Core;
  4072. @@ -680,19 +1036,94 @@
  4073.         return true;
  4074.  }
  4075.  
  4076. +bool CCharacter::Freeze(int ticks)
  4077. +{
  4078. +       if (ticks <= 1)
  4079. +               return false;
  4080. +       if (frz_tick > 0)//already frozen
  4081. +       {
  4082. +               if (frz_tick + REFREEZE_INTERVAL_TICKS > Server()->Tick())
  4083. +               return true;
  4084. +       }
  4085. +       else
  4086. +       {
  4087. +               frz_start=Server()->Tick();
  4088. +               epicninjaannounced=0;
  4089. +               lastepicninja=Server()->Tick()-5*Server()->TickSpeed();
  4090. +       }
  4091. +       frz_tick=Server()->Tick();
  4092. +       frz_time=ticks;
  4093. +       m_Ninja.m_ActivationTick = Server()->Tick();
  4094. +       m_aWeapons[WEAPON_NINJA].m_Got = true;
  4095. +       m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
  4096. +       if (m_ActiveWeapon != WEAPON_NINJA)
  4097. +       {
  4098. +               SetWeapon(WEAPON_NINJA);
  4099. +       }
  4100. +       return true;
  4101. +}
  4102. +
  4103. +bool CCharacter::Unfreeze()
  4104. +{
  4105. +       m_Ninja.m_CurrentMoveTime=-1;//prevent magic teleport when unfreezing while epic ninja
  4106. +
  4107. +       if (frz_time > 0)
  4108. +       {
  4109. +               frz_tick = frz_time = frz_start = 0;
  4110. +               m_aWeapons[WEAPON_NINJA].m_Got = false;
  4111. +               CanFire = true;
  4112. +               if(m_LastWeapon < 0 || m_LastWeapon >= NUM_WEAPONS || m_LastWeapon  == WEAPON_NINJA || (!m_aWeapons[m_LastWeapon].m_Got)) m_LastWeapon = WEAPON_HAMMER;
  4113. +               SetWeapon(m_LastWeapon);
  4114. +               epicninjaannounced=0;
  4115. +               return true;
  4116. +       }
  4117. +       return false;
  4118. +
  4119. +return true;
  4120. +}
  4121. +
  4122. +void CCharacter::TellPowerUpInfo(int ClientID, int Skill)
  4123. +{
  4124. +       static char bBuf[512];
  4125. +       switch(Skill)
  4126. +       {
  4127. +               case PUP_JUMP:
  4128. +                       str_format(bBuf, 128, "You got an extra jump");
  4129. +                       break;
  4130. +               case PUP_HAMMER:
  4131. +                       str_format(bBuf, 128, "Hammer power increased");
  4132. +                       break;
  4133. +               case PUP_LFREEZE:
  4134. +                       str_format(bBuf, 128, "Enemy freeze time increased");
  4135. +                       break;
  4136. +               case PUP_SFREEZE:
  4137. +                       str_format(bBuf, 128, "Own freeze time shortened");
  4138. +                       break;
  4139. +               case PUP_HOOKDUR:
  4140. +                       str_format(bBuf, 128, "Hook duration increased");
  4141. +                       break;
  4142. +               case PUP_HOOKLEN:
  4143. +                       str_format(bBuf, 128, "Hook length extended");
  4144. +                       break;
  4145. +               case PUP_WALKSPD:
  4146. +                       str_format(bBuf, 128, "Walk speed increased");
  4147. +                       break;
  4148. +               case PUP_EPICNINJA:
  4149. +                       str_format(bBuf, 128, "Freeze attack");
  4150. +                       break;
  4151. +               default:
  4152. +                       str_format(bBuf, 128, "Bug! Contact an admin!");
  4153. +                       break;
  4154. +       }
  4155. +       GameServer()->SendChatTarget(ClientID, bBuf);
  4156. +}
  4157. +
  4158.  void CCharacter::Die(int Killer, int Weapon)
  4159.  {
  4160.         // we got to wait 0.5 secs before respawning
  4161. -       m_Alive = false;
  4162.         m_pPlayer->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  4163.         int ModeSpecial = GameServer()->m_pController->OnCharacterDeath(this, GameServer()->m_apPlayers[Killer], Weapon);
  4164.  
  4165. -       char aBuf[256];
  4166. -       str_format(aBuf, sizeof(aBuf), "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d",
  4167. -               Killer, Server()->ClientName(Killer),
  4168. -               m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), Weapon, ModeSpecial);
  4169. -       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  4170. -
  4171.         // send the kill message
  4172.         CNetMsg_Sv_KillMsg Msg;
  4173.         Msg.m_Killer = Killer;
  4174. @@ -705,8 +1136,8 @@
  4175.         GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE);
  4176.  
  4177.         // this is for auto respawn after 3 secs
  4178. -       m_pPlayer->m_DieTick = Server()->Tick();
  4179. -
  4180. +//     m_pPlayer->m_DieTick = Server()->Tick();
  4181. +       m_Alive = false;
  4182.         GameServer()->m_World.RemoveEntity(this);
  4183.         GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
  4184.         GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID());
  4185. @@ -715,8 +1146,10 @@
  4186.  bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
  4187.  {
  4188.         m_Core.m_Vel += Force;
  4189. +      
  4190. +       /*if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage)
  4191.  
  4192. -       if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From))
  4193. +       if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage)
  4194.                 return false;
  4195.  
  4196.         // m_pPlayer only inflicts half damage on self
  4197. @@ -735,9 +1168,14 @@
  4198.         {
  4199.                 m_DamageTaken = 0;
  4200.                 GameServer()->CreateDamageInd(m_Pos, 0, Dmg);
  4201. +       }*/
  4202. +
  4203. +       if(Weapon == WEAPON_NINJA)
  4204. +       {
  4205. +               Freeze(ft + GameServer()->m_apPlayers[From]->Skills[PUP_LFREEZE] * (Server()->TickSpeed()>>1));
  4206.         }
  4207.  
  4208. -       if(Dmg)
  4209. +       /*if(Dmg)
  4210.         {
  4211.                 if(m_Armor)
  4212.                 {
  4213. @@ -766,12 +1204,13 @@
  4214.  
  4215.         // do damage Hit sound
  4216.         if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
  4217. +               */GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, CmaskOne(From));
  4218. +/*
  4219.         {
  4220. -               int Mask = CmaskOne(From);
  4221. +               int64_t Mask = CmaskOne(From);
  4222.                 for(int i = 0; i < MAX_CLIENTS; i++)
  4223.                 {
  4224. -                       if(GameServer()->m_apPlayers[i] && (GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS ||  GameServer()->m_apPlayers[i]->m_DeadSpecMode) &&
  4225. -                               GameServer()->m_apPlayers[i]->GetSpectatorID() == From)
  4226. +                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS && GameServer()->m_apPlayers[i]->m_SpectatorID == From)
  4227.                                 Mask |= CmaskOne(i);
  4228.                 }
  4229.                 GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, Mask);
  4230. @@ -800,19 +1239,24 @@
  4231.                 GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG);
  4232.         else
  4233.                 GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT);
  4234. -
  4235. +*/
  4236.         m_EmoteType = EMOTE_PAIN;
  4237.         m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000;
  4238. -
  4239. +      
  4240.         return true;
  4241.  }
  4242.  
  4243.  void CCharacter::Snap(int SnappingClient)
  4244.  {
  4245. +       int id = m_pPlayer->GetCID();
  4246. +
  4247. +       if (!Server()->Translate(id, SnappingClient))
  4248. +               return;
  4249. +
  4250.         if(NetworkClipped(SnappingClient))
  4251.                 return;
  4252.  
  4253. -       CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character)));
  4254. +       CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, id, sizeof(CNetObj_Character)));
  4255.         if(!pCharacter)
  4256.                 return;
  4257.  
  4258. @@ -833,10 +1277,15 @@
  4259.         // set emote
  4260.         if (m_EmoteStop < Server()->Tick())
  4261.         {
  4262. -               m_EmoteType = EMOTE_NORMAL;
  4263. +               m_EmoteType = m_DefEmote;
  4264.                 m_EmoteStop = -1;
  4265.         }
  4266.  
  4267. +       if (pCharacter->m_HookedPlayer != -1)
  4268. +       {
  4269. +               if (!Server()->Translate(pCharacter->m_HookedPlayer, SnappingClient))
  4270. +                       pCharacter->m_HookedPlayer = -1;
  4271. +       }
  4272.         pCharacter->m_Emote = m_EmoteType;
  4273.  
  4274.         pCharacter->m_AmmoCount = 0;
  4275. @@ -849,7 +1298,7 @@
  4276.         pCharacter->m_Direction = m_Input.m_Direction;
  4277.  
  4278.         if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 ||
  4279. -               (!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID()))
  4280. +               (!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID))
  4281.         {
  4282.                 pCharacter->m_Health = m_Health;
  4283.                 pCharacter->m_Armor = m_Armor;
  4284. @@ -862,4 +1311,33 @@
  4285.                 if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5)
  4286.                         pCharacter->m_Emote = EMOTE_BLINK;
  4287.         }
  4288. +
  4289. +       pCharacter->m_PlayerFlags = GetPlayer()->m_PlayerFlags;
  4290.  }
  4291. +
  4292. +void CCharacter::FreezeTik()
  4293. +{
  4294. +       ft = Server()->TickSpeed() * 3;
  4295. +       hooked = lasthookedat > lasthammeredat;
  4296. +       by = hooked ? lasthookedby : lasthammeredby;
  4297. +       add=0;
  4298. +       if ((wasout || frz_tick == 0) && (((lasthookedat + (Server()->TickSpeed()<<1)) > Server()->Tick()) || ((lasthammeredat + Server()->TickSpeed()) > Server()->Tick())))
  4299. +       {
  4300. +               if (GameServer()->m_apPlayers[by] && GameServer()->m_apPlayers[by]->GetCharacter())
  4301. +               {
  4302. +                       add = GameServer()->m_apPlayers[by]->Skills[PUP_LFREEZE];
  4303. +               }
  4304. +               blockedby=by;
  4305. +               if (blockedby>=0) blocktime=ft+(add * (Server()->TickSpeed()>>1));
  4306. +               } else {
  4307. +                       if (frz_tick==0)
  4308. +                       {
  4309. +                               blockedby=-1;
  4310. +                       }
  4311. +                       if (blockedby>=0)
  4312. +                       ft=blocktime;
  4313. +               }
  4314. +               add -=m_pPlayer->Skills[PUP_SFREEZE];
  4315. +               ft += (add * (Server()->TickSpeed()>>1));
  4316. +               wasout=0;
  4317. +       }
  4318. diff -Naur ../teeworlds/src/game/server/entities/character.h src/game/server/entities/character.h
  4319. --- ../teeworlds/src/game/server/entities/character.h   2012-06-26 16:53:53.388863852 +1000
  4320. +++ src/game/server/entities/character.h        2012-07-08 19:42:32.942259106 +1000
  4321. @@ -4,7 +4,27 @@
  4322.  #define GAME_SERVER_ENTITIES_CHARACTER_H
  4323.  
  4324.  #include <game/server/entity.h>
  4325. +#include <game/generated/server_data.h>
  4326. +#include <game/generated/protocol.h>
  4327.  
  4328. +#include <game/gamecore.h>
  4329. +
  4330. +#define REFREEZE_INTERVAL_TICKS (Server()->TickSpeed() * 1)
  4331. +
  4332. +#define COL_BLUE 9502541
  4333. +#define COL_GREEN 5373773
  4334. +#define COL_WHITE 16777215
  4335. +#define COL_GREY 1
  4336. +#define COL_RED 65280
  4337. +#define COL_YELLOW 2883328
  4338. +#define COL_PINK 14090075
  4339. +
  4340. +enum
  4341. +{
  4342. +       WEAPON_GAME = -3, // team switching etc
  4343. +       WEAPON_SELF = -2, // console kill command
  4344. +       WEAPON_WORLD = -1, // death tiles etc
  4345. +};
  4346.  
  4347.  class CCharacter : public CEntity
  4348.  {
  4349. @@ -22,7 +42,8 @@
  4350.         virtual void TickDefered();
  4351.         virtual void TickPaused();
  4352.         virtual void Snap(int SnappingClient);
  4353. -
  4354. +       virtual void HandleFreeze();
  4355. +       virtual void FreezeTik();      
  4356.         bool IsGrounded();
  4357.  
  4358.         void SetWeapon(int W);
  4359. @@ -50,16 +71,31 @@
  4360.         void GiveNinja();
  4361.  
  4362.         void SetEmote(int Emote, int Tick);
  4363. -
  4364. +       void SetEmoteType(int EmoteType) { m_EmoteType = EmoteType; };
  4365. +      
  4366.         bool IsAlive() const { return m_Alive; }
  4367.         class CPlayer *GetPlayer() { return m_pPlayer; }
  4368. -
  4369. +       void SetEmoteStop(int EmoteStop) { m_EmoteStop = EmoteStop; };
  4370. +       /*BBM stuff*/
  4371. +       bool Freeze(int time);
  4372. +       bool Unfreeze();
  4373. +       int m_EmoteStop;
  4374. +       int m_DefEmote;
  4375. +       int m_DefEmoteReset;
  4376. +       int ft;
  4377. +       int m_MuteInfo;
  4378. +       bool CanFire;
  4379. +       int frz_tick;//will get updated on every REFREEZE_INTERVAL ticks
  4380. +       int by;
  4381. +       int CollisonMate;
  4382. +/*      ################         */
  4383.  private:
  4384. +       void TellPowerUpInfo(int ClientID, int Skill);
  4385. +
  4386.         // player controlling this character
  4387.         class CPlayer *m_pPlayer;
  4388.  
  4389.         bool m_Alive;
  4390. -
  4391.         // weapon info
  4392.         CEntity *m_apHitObjects[10];
  4393.         int m_NumObjectsHit;
  4394. @@ -83,7 +119,6 @@
  4395.         int m_DamageTaken;
  4396.  
  4397.         int m_EmoteType;
  4398. -       int m_EmoteStop;
  4399.  
  4400.         // last tick that the player took any action ie some input
  4401.         int m_LastAction;
  4402. @@ -103,6 +138,23 @@
  4403.         int m_Health;
  4404.         int m_Armor;
  4405.  
  4406. +       int frz_time;//will be higher when blocker has lfreeze, for instance
  4407. +       int frz_start;//will be set on the first freeze
  4408. +
  4409. +       int lastcolfrz;
  4410. +       int lastloadsave;
  4411. +       int lasthammeredby, lasthammeredat;
  4412. +       int lasthookedby, lasthookedat;
  4413. +       int LastUpdate;
  4414. +       int wasout;
  4415. +       int lastepicninja;
  4416. +       int epicninjaannounced;
  4417. +       int blockedby;
  4418. +       int blocktime;
  4419. +       int add;
  4420. +       int hooked;
  4421. +       vec2 epicninjaoldpos;
  4422. +
  4423.         // ninja
  4424.         struct
  4425.         {
  4426. diff -Naur ../teeworlds/src/game/server/entities/flag.cpp src/game/server/entities/flag.cpp
  4427. --- ../teeworlds/src/game/server/entities/flag.cpp      2012-06-26 16:53:53.388863852 +1000
  4428. +++ src/game/server/entities/flag.cpp   2012-07-08 19:42:32.842259599 +1000
  4429. @@ -1,8 +1,6 @@
  4430.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  4431.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4432.  #include <game/server/gamecontext.h>
  4433. -
  4434. -#include "character.h"
  4435.  #include "flag.h"
  4436.  
  4437.  CFlag::CFlag(CGameWorld *pGameWorld, int Team)
  4438. diff -Naur ../teeworlds/src/game/server/entities/laser.cpp src/game/server/entities/laser.cpp
  4439. --- ../teeworlds/src/game/server/entities/laser.cpp     2012-06-26 16:53:53.388863852 +1000
  4440. +++ src/game/server/entities/laser.cpp  2012-07-08 19:42:32.842259599 +1000
  4441. @@ -1,8 +1,7 @@
  4442.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  4443.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4444. +#include <game/generated/protocol.h>
  4445.  #include <game/server/gamecontext.h>
  4446. -
  4447. -#include "character.h"
  4448.  #include "laser.h"
  4449.  
  4450.  CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner)
  4451. @@ -30,7 +29,7 @@
  4452.         m_From = From;
  4453.         m_Pos = At;
  4454.         m_Energy = -1;
  4455. -       pHit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_LASER);
  4456. +       pHit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE);
  4457.         return true;
  4458.  }
  4459.  
  4460. @@ -67,7 +66,7 @@
  4461.                         if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum)
  4462.                                 m_Energy = -1;
  4463.  
  4464. -                       GameServer()->CreateSound(m_Pos, SOUND_LASER_BOUNCE);
  4465. +                       GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE);
  4466.                 }
  4467.         }
  4468.         else
  4469. diff -Naur ../teeworlds/src/game/server/entities/pickup.cpp src/game/server/entities/pickup.cpp
  4470. --- ../teeworlds/src/game/server/entities/pickup.cpp    2012-06-26 16:53:53.388863852 +1000
  4471. +++ src/game/server/entities/pickup.cpp 2012-07-08 19:42:32.842259599 +1000
  4472. @@ -1,16 +1,14 @@
  4473.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  4474.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4475. -#include <game/generated/server_data.h>
  4476. +#include <game/generated/protocol.h>
  4477.  #include <game/server/gamecontext.h>
  4478. -#include <game/server/player.h>
  4479. -
  4480. -#include "character.h"
  4481.  #include "pickup.h"
  4482.  
  4483. -CPickup::CPickup(CGameWorld *pGameWorld, int Type)
  4484. +CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType)
  4485.  : CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP)
  4486.  {
  4487.         m_Type = Type;
  4488. +       m_Subtype = SubType;
  4489.         m_ProximityRadius = PickupPhysSize;
  4490.  
  4491.         Reset();
  4492. @@ -36,7 +34,7 @@
  4493.                         // respawn
  4494.                         m_SpawnTick = -1;
  4495.  
  4496. -                       if(m_Type == PICKUP_GRENADE || m_Type == PICKUP_SHOTGUN || m_Type == PICKUP_LASER)
  4497. +                       if(m_Type == POWERUP_WEAPON)
  4498.                                 GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SPAWN);
  4499.                 }
  4500.                 else
  4501. @@ -50,7 +48,7 @@
  4502.                 int RespawnTime = -1;
  4503.                 switch (m_Type)
  4504.                 {
  4505. -                       case PICKUP_HEALTH:
  4506. +                       case POWERUP_HEALTH:
  4507.                                 if(pChr->IncreaseHealth(1))
  4508.                                 {
  4509.                                         GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH);
  4510. @@ -58,7 +56,7 @@
  4511.                                 }
  4512.                                 break;
  4513.  
  4514. -                       case PICKUP_ARMOR:
  4515. +                       case POWERUP_ARMOR:
  4516.                                 if(pChr->IncreaseArmor(1))
  4517.                                 {
  4518.                                         GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR);
  4519. @@ -66,35 +64,27 @@
  4520.                                 }
  4521.                                 break;
  4522.  
  4523. -                       case PICKUP_GRENADE:
  4524. -                               if(pChr->GiveWeapon(WEAPON_GRENADE, 10))
  4525. -                               {
  4526. -                                       RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
  4527. -                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE);
  4528. -                                       if(pChr->GetPlayer())
  4529. -                                               GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), WEAPON_GRENADE);
  4530. -                               }
  4531. -                               break;
  4532. -                       case PICKUP_SHOTGUN:
  4533. -                               if(pChr->GiveWeapon(WEAPON_SHOTGUN, 10))
  4534. -                               {
  4535. -                                       RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
  4536. -                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
  4537. -                                       if(pChr->GetPlayer())
  4538. -                                               GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), WEAPON_SHOTGUN);
  4539. -                               }
  4540. -                               break;
  4541. -                       case PICKUP_LASER:
  4542. -                               if(pChr->GiveWeapon(WEAPON_LASER, 10))
  4543. +                       case POWERUP_WEAPON:
  4544. +                               if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS)
  4545.                                 {
  4546. -                                       RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
  4547. -                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
  4548. -                                       if(pChr->GetPlayer())
  4549. -                                               GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), WEAPON_LASER);
  4550. +                                       if(pChr->GiveWeapon(m_Subtype, 10))
  4551. +                                       {
  4552. +                                               RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime;
  4553. +
  4554. +                                               if(m_Subtype == WEAPON_GRENADE)
  4555. +                                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE);
  4556. +                                               else if(m_Subtype == WEAPON_SHOTGUN)
  4557. +                                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
  4558. +                                               else if(m_Subtype == WEAPON_RIFLE)
  4559. +                                                       GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN);
  4560. +
  4561. +                                               if(pChr->GetPlayer())
  4562. +                                                       GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype);
  4563. +                                       }
  4564.                                 }
  4565.                                 break;
  4566.  
  4567. -                       case PICKUP_NINJA:
  4568. +                       case POWERUP_NINJA:
  4569.                                 {
  4570.                                         // activate ninja on target player
  4571.                                         pChr->GiveNinja();
  4572. @@ -120,7 +110,7 @@
  4573.                 {
  4574.                         char aBuf[256];
  4575.                         str_format(aBuf, sizeof(aBuf), "pickup player='%d:%s' item=%d/%d",
  4576. -                               pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type);
  4577. +                               pChr->GetPlayer()->GetCID(), Server()->ClientName(pChr->GetPlayer()->GetCID()), m_Type, m_Subtype);
  4578.                         GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  4579.                         m_SpawnTick = Server()->Tick() + Server()->TickSpeed() * RespawnTime;
  4580.                 }
  4581. @@ -145,4 +135,5 @@
  4582.         pP->m_X = (int)m_Pos.x;
  4583.         pP->m_Y = (int)m_Pos.y;
  4584.         pP->m_Type = m_Type;
  4585. +       pP->m_Subtype = m_Subtype;
  4586.  }
  4587. diff -Naur ../teeworlds/src/game/server/entities/pickup.h src/game/server/entities/pickup.h
  4588. --- ../teeworlds/src/game/server/entities/pickup.h      2012-06-26 16:53:53.388863852 +1000
  4589. +++ src/game/server/entities/pickup.h   2012-07-08 19:42:32.842259599 +1000
  4590. @@ -10,7 +10,7 @@
  4591.  class CPickup : public CEntity
  4592.  {
  4593.  public:
  4594. -       CPickup(CGameWorld *pGameWorld, int Type);
  4595. +       CPickup(CGameWorld *pGameWorld, int Type, int SubType = 0);
  4596.  
  4597.         virtual void Reset();
  4598.         virtual void Tick();
  4599. @@ -19,6 +19,7 @@
  4600.  
  4601.  private:
  4602.         int m_Type;
  4603. +       int m_Subtype;
  4604.         int m_SpawnTick;
  4605.  };
  4606.  
  4607. diff -Naur ../teeworlds/src/game/server/entities/projectile.cpp src/game/server/entities/projectile.cpp
  4608. --- ../teeworlds/src/game/server/entities/projectile.cpp        2012-06-26 16:53:53.388863852 +1000
  4609. +++ src/game/server/entities/projectile.cpp     2012-07-08 19:42:32.942259106 +1000
  4610. @@ -1,8 +1,7 @@
  4611.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  4612.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4613. +#include <game/generated/protocol.h>
  4614.  #include <game/server/gamecontext.h>
  4615. -
  4616. -#include "character.h"
  4617.  #include "projectile.h"
  4618.  
  4619.  CProjectile::CProjectile(CGameWorld *pGameWorld, int Type, int Owner, vec2 Pos, vec2 Dir, int Span,
  4620. @@ -75,9 +74,14 @@
  4621.  
  4622.                 if(m_Explosive)
  4623.                         GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false);
  4624. -
  4625. -               else if(TargetChr)
  4626. -                       TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon);
  4627. +                      
  4628. +               //else if(TargetChr)
  4629. +               //      TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon);
  4630. +               else if (m_Weapon == WEAPON_GUN)
  4631. +               {
  4632. +                       GameServer()->CreateDamageInd(CurPos, -atan2(m_Direction.x, m_Direction.y), 5);
  4633. +                       GameServer()->m_World.DestroyEntity(this);
  4634. +               }
  4635.  
  4636.                 GameServer()->m_World.DestroyEntity(this);
  4637.         }
  4638. diff -Naur ../teeworlds/src/game/server/entity.cpp src/game/server/entity.cpp
  4639. --- ../teeworlds/src/game/server/entity.cpp     2012-06-26 16:53:53.388863852 +1000
  4640. +++ src/game/server/entity.cpp  2012-07-08 19:28:03.414258934 +1000
  4641. @@ -3,7 +3,6 @@
  4642.  
  4643.  #include "entity.h"
  4644.  #include "gamecontext.h"
  4645. -#include "player.h"
  4646.  
  4647.  //////////////////////////////////////////////////
  4648.  // Entity
  4649. diff -Naur ../teeworlds/src/game/server/entity.h src/game/server/entity.h
  4650. --- ../teeworlds/src/game/server/entity.h       2012-06-26 16:53:53.388863852 +1000
  4651. +++ src/game/server/entity.h    2012-07-08 19:42:32.842259599 +1000
  4652. @@ -3,11 +3,52 @@
  4653.  #ifndef GAME_SERVER_ENTITY_H
  4654.  #define GAME_SERVER_ENTITY_H
  4655.  
  4656. +#include <new>
  4657.  #include <base/vmath.h>
  4658. -
  4659.  #include <game/server/gameworld.h>
  4660.  
  4661. -#include "alloc.h"
  4662. +#define MACRO_ALLOC_HEAP() \
  4663. +       public: \
  4664. +       void *operator new(size_t Size) \
  4665. +       { \
  4666. +               void *p = mem_alloc(Size, 1); \
  4667. +               /*dbg_msg("", "++ %p %d", p, size);*/ \
  4668. +               mem_zero(p, Size); \
  4669. +               return p; \
  4670. +       } \
  4671. +       void operator delete(void *pPtr) \
  4672. +       { \
  4673. +               /*dbg_msg("", "-- %p", p);*/ \
  4674. +               mem_free(pPtr); \
  4675. +       } \
  4676. +       private:
  4677. +
  4678. +#define MACRO_ALLOC_POOL_ID() \
  4679. +       public: \
  4680. +       void *operator new(size_t Size, int id); \
  4681. +       void operator delete(void *p); \
  4682. +       private:
  4683. +
  4684. +#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, PoolSize) \
  4685. +       static char ms_PoolData##POOLTYPE[PoolSize][sizeof(POOLTYPE)] = {{0}}; \
  4686. +       static int ms_PoolUsed##POOLTYPE[PoolSize] = {0}; \
  4687. +       void *POOLTYPE::operator new(size_t Size, int id) \
  4688. +       { \
  4689. +               dbg_assert(sizeof(POOLTYPE) == Size, "size error"); \
  4690. +               dbg_assert(!ms_PoolUsed##POOLTYPE[id], "already used"); \
  4691. +               /*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \
  4692. +               ms_PoolUsed##POOLTYPE[id] = 1; \
  4693. +               mem_zero(ms_PoolData##POOLTYPE[id], Size); \
  4694. +               return ms_PoolData##POOLTYPE[id]; \
  4695. +       } \
  4696. +       void POOLTYPE::operator delete(void *p) \
  4697. +       { \
  4698. +               int id = (POOLTYPE*)p - (POOLTYPE*)ms_PoolData##POOLTYPE; \
  4699. +               dbg_assert(ms_PoolUsed##POOLTYPE[id], "not used"); \
  4700. +               /*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \
  4701. +               ms_PoolUsed##POOLTYPE[id] = 0; \
  4702. +               mem_zero(ms_PoolData##POOLTYPE[id], sizeof(POOLTYPE)); \
  4703. +       }
  4704.  
  4705.  /*
  4706.         Class: Entity
  4707. diff -Naur ../teeworlds/src/game/server/eventhandler.cpp src/game/server/eventhandler.cpp
  4708. --- ../teeworlds/src/game/server/eventhandler.cpp       2012-06-26 16:53:53.388863852 +1000
  4709. +++ src/game/server/eventhandler.cpp    2012-07-08 19:28:03.414258934 +1000
  4710. @@ -2,7 +2,6 @@
  4711.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4712.  #include "eventhandler.h"
  4713.  #include "gamecontext.h"
  4714. -#include "player.h"
  4715.  
  4716.  //////////////////////////////////////////////////
  4717.  // Event handler
  4718. @@ -18,7 +17,7 @@
  4719.         m_pGameServer = pGameServer;
  4720.  }
  4721.  
  4722. -void *CEventHandler::Create(int Type, int Size, int Mask)
  4723. +void *CEventHandler::Create(int Type, int Size, int64_t Mask)
  4724.  {
  4725.         if(m_NumEvents == MAX_EVENTS)
  4726.                 return 0;
  4727. diff -Naur ../teeworlds/src/game/server/eventhandler.h src/game/server/eventhandler.h
  4728. --- ../teeworlds/src/game/server/eventhandler.h 2012-06-26 16:53:53.392865827 +1000
  4729. +++ src/game/server/eventhandler.h      2012-07-08 19:42:32.842259599 +1000
  4730. @@ -3,6 +3,14 @@
  4731.  #ifndef GAME_SERVER_EVENTHANDLER_H
  4732.  #define GAME_SERVER_EVENTHANDLER_H
  4733.  
  4734. +#ifdef _MSC_VER
  4735. +typedef __int32 int32_t;
  4736. +typedef unsigned __int32 uint32_t;
  4737. +typedef __int64 int64_t;
  4738. +typedef unsigned __int64 uint64_t;
  4739. +#else
  4740. +#include <stdint.h>
  4741. +#endif
  4742.  //
  4743.  class CEventHandler
  4744.  {
  4745. @@ -12,7 +20,7 @@
  4746.         int m_aTypes[MAX_EVENTS]; // TODO: remove some of these arrays
  4747.         int m_aOffsets[MAX_EVENTS];
  4748.         int m_aSizes[MAX_EVENTS];
  4749. -       int m_aClientMasks[MAX_EVENTS];
  4750. +       int64_t m_aClientMasks[MAX_EVENTS];
  4751.         char m_aData[MAX_DATASIZE];
  4752.  
  4753.         class CGameContext *m_pGameServer;
  4754. @@ -24,7 +32,7 @@
  4755.         void SetGameServer(CGameContext *pGameServer);
  4756.  
  4757.         CEventHandler();
  4758. -       void *Create(int Type, int Size, int Mask = -1);
  4759. +       void *Create(int Type, int Size, int64_t Mask = -1);
  4760.         void Clear();
  4761.         void Snap(int SnappingClient);
  4762.  };
  4763. diff -Naur ../teeworlds/src/game/server/gamecontext.cpp src/game/server/gamecontext.cpp
  4764. --- ../teeworlds/src/game/server/gamecontext.cpp        2012-07-08 00:31:07.989177105 +1000
  4765. +++ src/game/server/gamecontext.cpp     2012-07-08 19:42:32.950258935 +1000
  4766. @@ -1,24 +1,18 @@
  4767.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  4768.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  4769. +#include <new>
  4770.  #include <base/math.h>
  4771. -
  4772.  #include <engine/shared/config.h>
  4773. -#include <engine/shared/memheap.h>
  4774.  #include <engine/map.h>
  4775. -
  4776. +#include <engine/console.h>
  4777. +#include "gamecontext.h"
  4778. +#include <game/version.h>
  4779.  #include <game/collision.h>
  4780.  #include <game/gamecore.h>
  4781. -#include <game/version.h>
  4782. -
  4783. -#include "entities/character.h"
  4784. -#include "gamemodes/ctf.h"
  4785.  #include "gamemodes/dm.h"
  4786. -#include "gamemodes/lms.h"
  4787. -#include "gamemodes/mod.h"
  4788. -#include "gamemodes/sur.h"
  4789.  #include "gamemodes/tdm.h"
  4790. -#include "gamecontext.h"
  4791. -#include "player.h"
  4792. +#include "gamemodes/ctf.h"
  4793. +#include "gamemodes/mod.h"
  4794.  
  4795.  enum
  4796.  {
  4797. @@ -189,7 +183,7 @@
  4798.         }
  4799.  }
  4800.  
  4801. -void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask)
  4802. +void CGameContext::CreateSound(vec2 Pos, int Sound, int64_t Mask)
  4803.  {
  4804.         if (Sound < 0)
  4805.                 return;
  4806. @@ -233,6 +227,7 @@
  4807.  }
  4808.  
  4809.  
  4810. +
  4811.  void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText)
  4812.  {
  4813.         char aBuf[256];
  4814. @@ -269,6 +264,7 @@
  4815.         }
  4816.  }
  4817.  
  4818. +
  4819.  void CGameContext::SendEmoticon(int ClientID, int Emoticon)
  4820.  {
  4821.         CNetMsg_Sv_Emoticon Msg;
  4822. @@ -347,25 +343,28 @@
  4823.  void CGameContext::SendVoteStatus(int ClientID, int Total, int Yes, int No)
  4824.  {
  4825.         CNetMsg_Sv_VoteStatus Msg = {0};
  4826. -       Msg.m_Total = Total;
  4827. -       Msg.m_Yes = Yes;
  4828. -       Msg.m_No = No;
  4829. -       Msg.m_Pass = Total - (Yes+No);
  4830. +       if (Total<=16)
  4831. +       {
  4832. +               Msg.m_Total = Total;
  4833. +               Msg.m_Yes = Yes;
  4834. +               Msg.m_No = No;
  4835. +               Msg.m_Pass = Total - (Yes+No);
  4836. +       } else {
  4837. +               double f = Total/16.;
  4838. +               Msg.m_Total = (int)(Total*f);
  4839. +               Msg.m_Yes = (int)(Yes*f);
  4840. +               Msg.m_No = (int)(No*f);
  4841. +               Msg.m_Pass = (int)((Total - (Yes+No))*f);
  4842. +       }
  4843.  
  4844.         Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
  4845.  
  4846.  }
  4847.  
  4848. -void CGameContext::AbortVoteOnDisconnect(int ClientID)
  4849. +void CGameContext::AbortVoteKickOnDisconnect(int ClientID)
  4850.  {
  4851. -       if(m_VoteCloseTime && ClientID == m_VoteClientID && (!str_comp_num(m_aVoteCommand, "kick ", 5) ||
  4852. -               !str_comp_num(m_aVoteCommand, "set_team ", 9) || (!str_comp_num(m_aVoteCommand, "ban ", 4) && Server()->IsBanned(ClientID))))
  4853. -               m_VoteCloseTime = -1;
  4854. -}
  4855. -
  4856. -void CGameContext::AbortVoteOnTeamChange(int ClientID)
  4857. -{
  4858. -       if(m_VoteCloseTime && ClientID == m_VoteClientID && !str_comp_num(m_aVoteCommand, "set_team ", 9))
  4859. +       if(m_VoteCloseTime && ((!str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientID) ||
  4860. +               (!str_comp_num(m_aVoteCommand, "set_team ", 9) && str_toint(&m_aVoteCommand[9]) == ClientID)))
  4861.                 m_VoteCloseTime = -1;
  4862.  }
  4863.  
  4864. @@ -376,11 +375,9 @@
  4865.         if(!m_pController)
  4866.                 return;
  4867.  
  4868. -       if(     str_comp(m_pController->GetGameType(), "DM")==0 ||
  4869. -               str_comp(m_pController->GetGameType(), "TDM")==0 ||
  4870. -               str_comp(m_pController->GetGameType(), "CTF")==0 ||
  4871. -               str_comp(m_pController->GetGameType(), "LMS")==0 ||
  4872. -               str_comp(m_pController->GetGameType(), "SUR")==0)
  4873. +       if(     str_comp(m_pController->m_pGameType, "DM")==0 ||
  4874. +               str_comp(m_pController->m_pGameType, "TDM")==0 ||
  4875. +               str_comp(m_pController->m_pGameType, "CTF")==0)
  4876.         {
  4877.                 CTuningParams p;
  4878.                 if(mem_comp(&p, &m_Tuning, sizeof(p)) != 0)
  4879. @@ -391,6 +388,7 @@
  4880.         }
  4881.  }
  4882.  
  4883. +
  4884.  void CGameContext::SendTuningParams(int ClientID)
  4885.  {
  4886.         CheckPureTuning();
  4887. @@ -412,8 +410,10 @@
  4888.         for(int i = 0; i < MAX_CLIENTS; ++i)
  4889.         {
  4890.                 if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  4891. -                       m_pController->DoTeamChange(m_apPlayers[i], m_apPlayers[i]->GetTeam()^1, false);
  4892. +                       m_apPlayers[i]->SetTeam(m_apPlayers[i]->GetTeam()^1, false);
  4893.         }
  4894. +
  4895. +       (void)m_pController->CheckTeamBalance();
  4896.  }
  4897.  
  4898.  void CGameContext::OnTick()
  4899. @@ -518,13 +518,13 @@
  4900.  
  4901.  
  4902.  #ifdef CONF_DEBUG
  4903. -       for(int i = 0; i < MAX_CLIENTS; i++)
  4904. +       if(g_Config.m_DbgDummies)
  4905.         {
  4906. -               if(m_apPlayers[i] && m_apPlayers[i]->IsDummy())
  4907. +               for(int i = 0; i < g_Config.m_DbgDummies ; i++)
  4908.                 {
  4909.                         CNetObj_PlayerInput Input = {0};
  4910.                         Input.m_Direction = (i&1)?-1:1;
  4911. -                       m_apPlayers[i]->OnPredictedInput(&Input);
  4912. +                       m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input);
  4913.                 }
  4914.         }
  4915.  #endif
  4916. @@ -533,7 +533,8 @@
  4917.  // Server hooks
  4918.  void CGameContext::OnClientDirectInput(int ClientID, void *pInput)
  4919.  {
  4920. -       m_apPlayers[ClientID]->OnDirectInput((CNetObj_PlayerInput *)pInput);
  4921. +       if(!m_World.m_Paused)
  4922. +               m_apPlayers[ClientID]->OnDirectInput((CNetObj_PlayerInput *)pInput);
  4923.  }
  4924.  
  4925.  void CGameContext::OnClientPredictedInput(int ClientID, void *pInput)
  4926. @@ -548,7 +549,10 @@
  4927.         m_apPlayers[ClientID]->Respawn();
  4928.         char aBuf[512];
  4929.         str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientID), m_pController->GetTeamName(m_apPlayers[ClientID]->GetTeam()));
  4930. -       SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  4931. +       SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  4932. +       SendChatTarget(ClientID, "BBMod Made by [BBM]Julian->Assange And [BBM]Learath2");
  4933. +       if(g_Config.m_SvWelcome[0]!=0)
  4934. +       SendChatTarget(ClientID,g_Config.m_SvWelcome);
  4935.  
  4936.         str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientID, Server()->ClientName(ClientID), m_apPlayers[ClientID]->GetTeam());
  4937.         Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  4938. @@ -556,12 +560,24 @@
  4939.         m_VoteUpdate = true;
  4940.  }
  4941.  
  4942. -void CGameContext::OnClientConnected(int ClientID, bool Dummy)
  4943. +void CGameContext::OnClientConnected(int ClientID)
  4944.  {
  4945. -       m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy);
  4946. -      
  4947. -       if(Dummy)
  4948. -               return;
  4949. +       // Check which team the player should be on
  4950. +       const int StartTeam = g_Config.m_SvTournamentMode ? TEAM_SPECTATORS : m_pController->GetAutoTeam(ClientID);
  4951. +
  4952. +       m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, StartTeam);
  4953. +       //players[client_id].init(client_id);
  4954. +       //players[client_id].client_id = client_id;
  4955. +
  4956. +       (void)m_pController->CheckTeamBalance();
  4957. +
  4958. +#ifdef CONF_DEBUG
  4959. +       if(g_Config.m_DbgDummies)
  4960. +       {
  4961. +               if(ClientID >= MAX_CLIENTS-g_Config.m_DbgDummies)
  4962. +                       return;
  4963. +       }
  4964. +#endif
  4965.  
  4966.         // send active vote
  4967.         if(m_VoteCloseTime)
  4968. @@ -573,20 +589,27 @@
  4969.         Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
  4970.  }
  4971.  
  4972. -void CGameContext::OnClientTeamChange(int ClientID)
  4973. -{
  4974. -       if(m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS)
  4975. -               AbortVoteOnTeamChange(ClientID);
  4976. -}
  4977. -
  4978.  void CGameContext::OnClientDrop(int ClientID, const char *pReason)
  4979.  {
  4980. -       AbortVoteOnDisconnect(ClientID);
  4981. -       m_pController->OnPlayerDisconnect(m_apPlayers[ClientID], pReason);
  4982. +       AbortVoteKickOnDisconnect(ClientID);
  4983. +       m_apPlayers[ClientID]->OnDisconnect(pReason);
  4984.         delete m_apPlayers[ClientID];
  4985.         m_apPlayers[ClientID] = 0;
  4986.  
  4987. +       (void)m_pController->CheckTeamBalance();
  4988.         m_VoteUpdate = true;
  4989. +
  4990. +       // update spectator modes
  4991. +       for(int i = 0; i < MAX_CLIENTS; ++i)
  4992. +       {
  4993. +               if(m_apPlayers[i] && m_apPlayers[i]->m_SpectatorID == ClientID)
  4994. +                       m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
  4995. +       }
  4996. +}
  4997. +
  4998. +char * CGameContext::HandleArguments(char *pString)
  4999. +{
  5000. +       return str_skip_whitespaces(str_skip_to_whitespace(pString));
  5001.  }
  5002.  
  5003.  void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
  5004. @@ -624,8 +647,110 @@
  5005.                                 *pMessage = ' ';
  5006.                         pMessage++;
  5007.                 }
  5008. -
  5009. -               SendChat(ClientID, Team, pMsg->m_pMessage);
  5010. +               CCharacter* pChr = pPlayer->GetCharacter();
  5011. +               if(m_apPlayers[ClientID]->m_Muted == 0 && !m_World.m_Paused)
  5012. +               {
  5013. +                       if(!str_comp_num(pMsg->m_pMessage, "/emote", 6) && !m_World.m_Paused && pChr && pPlayer)
  5014. +                       {
  5015. +                               pChr->m_DefEmoteReset = 0;
  5016. +                               if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "normal"))
  5017. +                               pChr->m_DefEmote =(EMOTE_NORMAL);
  5018. +
  5019. +                               else if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "surprise"))
  5020. +                               pChr->m_DefEmote =(EMOTE_SURPRISE);
  5021. +                               else if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "happy"))
  5022. +                               pChr->m_DefEmote =(EMOTE_HAPPY);
  5023. +                               else if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "pain"))
  5024. +                               pChr->m_DefEmote =(EMOTE_PAIN);
  5025. +                               else if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "blink"))
  5026. +                               pChr->m_DefEmote =(EMOTE_BLINK);
  5027. +                               else if (!str_comp_nocase(HandleArguments((char *)pMsg->m_pMessage), "angry"))
  5028. +                               pChr->m_DefEmote =(EMOTE_ANGRY);
  5029. +                               else
  5030. +                               {
  5031. +                                       SendChatTarget(ClientID, "Unknown Emote Emotes Are: Normal, Surprise, Happy, Pain, Blink And Close");
  5032. +                                       SendChatTarget(ClientID, "Emotes Are Used Like This: /emote ****");
  5033. +                               }
  5034. +                       }
  5035. +                       else if(!str_comp_nocase(pMsg->m_pMessage, "/info"))
  5036. +                       {
  5037. +                               SendChatTarget(ClientID, "****Mod by \"[BBM]Julian->Assange\" And Some Great Helps By \"Learath2\" <3****");
  5038. +                               SendChatTarget(ClientID, "Commands: /emote , /powerups , /colors");
  5039. +                       }
  5040. +                       else if(!str_comp_nocase(pMsg->m_pMessage, "/powerups"))
  5041. +                       {
  5042. +                               SendChatTarget(ClientID, "********Powerups*********");
  5043. +                               char aBuf[256];
  5044. +                               char PUP_NAME[8][32]= {"Jump", "Hammer", "Plus Enemy Freeze Time", "Minus Self Freeze Time", "Hook Duration", "Hook Length", "Run", "Epic Ninja"};
  5045. +                               for(int i = 0; i < NUM_PUPS; i++)
  5046. +                               {
  5047. +                                       str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->Skills[i]);
  5048. +                                       SendChatTarget(ClientID, aBuf);
  5049. +                               }
  5050. +                               SendChatTarget(ClientID, "**************************");
  5051. +                               return;
  5052. +                       }
  5053. +                       else if(!str_comp_nocase(pMsg->m_pMessage, "/colors"))
  5054. +                               {
  5055. +                                       SendChatTarget(ClientID, "*********Colors**********");
  5056. +                                       char aBuf[256];
  5057. +                                       char PUP_NAME[7][32]= {"Green", "Blue", "Red", "Pink", "Black", "White", "Yellow"};
  5058. +                                       for(int i = 0; i < 7; i++)
  5059. +                                       {
  5060. +                                               if(i == 0)
  5061. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoGreen);
  5062. +                                               if(i == 1)
  5063. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoBlue);
  5064. +                                               if(i == 2)
  5065. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoRed);
  5066. +                                               if(i == 3)
  5067. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoPink);
  5068. +                                               if(i == 4)
  5069. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoGrey);
  5070. +                                               if(i == 5)
  5071. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoWhite);
  5072. +                                               if(i == 6)
  5073. +                                               str_format(aBuf, sizeof(aBuf), "%s : %d", PUP_NAME[i], pPlayer->m_NoYellow);
  5074. +                                               SendChatTarget(ClientID, aBuf);
  5075. +                                       }
  5076. +                               SendChatTarget(ClientID, "*************************");
  5077. +                               return;
  5078. +                       }
  5079. +                       else if(!str_comp_num(pMsg->m_pMessage, "/", 1))
  5080. +                       SendChatTarget(ClientID, "Invalid command! do /info");
  5081. +                       else
  5082. +                       {      
  5083. +                               if(pPlayer->m_LastChatTime + Server()->TickSpeed() >= Server()->Tick() || str_comp_nocase(pMsg->m_pMessage, pPlayer->m_LastChatText) != 0)
  5084. +                               {
  5085. +                                       SendChat(ClientID, Team, pMsg->m_pMessage);
  5086. +                                       str_copy(pPlayer->m_LastChatText, pMsg->m_pMessage, sizeof(pPlayer->m_LastChatText));
  5087. +                                       pPlayer->m_LastChatTime = Server()->Tick();
  5088. +                               }
  5089. +                               else
  5090. +                               {
  5091. +                                       SendChat(ClientID, Team, pMsg->m_pMessage);
  5092. +                                       pPlayer->m_LastChatTime = Server()->Tick();
  5093. +                                       str_copy(pPlayer->m_LastChatText, pMsg->m_pMessage, sizeof(pPlayer->m_LastChatText));
  5094. +                                       pPlayer->m_MuteTimes = pPlayer->m_MuteTimes + 2;
  5095. +                               }
  5096. +                               if(pPlayer->m_MuteTimes == 10)
  5097. +                               {
  5098. +                                       pPlayer->m_Muted = Server()->TickSpeed() * g_Config.m_SvAutoMuteTime;
  5099. +                                       char aBuf[256];
  5100. +                                       str_format(aBuf, sizeof(aBuf), "You Are Muted For %d Seconds", m_apPlayers[ClientID]->m_Muted / Server()->TickSpeed());
  5101. +                                       SendChatTarget(ClientID, aBuf);
  5102. +                                       str_format(aBuf, sizeof(aBuf), "%s Is Muted For %d Seconds", Server()->ClientName(ClientID), m_apPlayers[ClientID]->m_Muted / Server()->TickSpeed());
  5103. +                                       SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  5104. +                                       pPlayer->m_MuteTimes = 0;
  5105. +                               }
  5106. +                       }
  5107. +               }
  5108. +               else
  5109. +               {
  5110. +                       char aBuf[256];
  5111. +                       str_format(aBuf, sizeof(aBuf), "You Can't Talk You Are Muted For Next %d Seconds", m_apPlayers[ClientID]->m_Muted / Server()->TickSpeed());
  5112. +                       SendChatTarget(ClientID, aBuf);
  5113. +               }
  5114.         }
  5115.         else if(MsgID == NETMSGTYPE_CL_CALLVOTE)
  5116.         {
  5117. @@ -687,7 +812,7 @@
  5118.                 }
  5119.                 else if(str_comp_nocase(pMsg->m_Type, "kick") == 0)
  5120.                 {
  5121. -                       if(!g_Config.m_SvVoteKick)
  5122. +                       if(!g_Config.m_SvVoteKick || g_Config.m_SvVoteKick)
  5123.                         {
  5124.                                 SendChatTarget(ClientID, "Server does not allow voting to kick players");
  5125.                                 return;
  5126. @@ -709,6 +834,9 @@
  5127.                         }
  5128.  
  5129.                         int KickID = str_toint(pMsg->m_Value);
  5130. +                       if (!Server()->ReverseTranslate(KickID, ClientID))
  5131. +                               return;
  5132. +
  5133.                         if(KickID < 0 || KickID >= MAX_CLIENTS || !m_apPlayers[KickID])
  5134.                         {
  5135.                                 SendChatTarget(ClientID, "Invalid client id to kick");
  5136. @@ -738,18 +866,22 @@
  5137.                                 Server()->GetClientAddr(KickID, aAddrStr, sizeof(aAddrStr));
  5138.                                 str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aAddrStr, g_Config.m_SvVoteKickBantime);
  5139.                         }
  5140. -                       m_VoteClientID = KickID;
  5141.                 }
  5142.                 else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0)
  5143.                 {
  5144. -                       if(!g_Config.m_SvVoteSpectate)
  5145. +                       if(!g_Config.m_SvVoteSpectate || g_Config.m_SvVoteSpectate)
  5146.                         {
  5147.                                 SendChatTarget(ClientID, "Server does not allow voting to move players to spectators");
  5148.                                 return;
  5149.                         }
  5150.  
  5151.                         int SpectateID = str_toint(pMsg->m_Value);
  5152. +
  5153. +                       if (!Server()->ReverseTranslate(SpectateID, ClientID))
  5154. +                               return;
  5155. +
  5156.                         if(SpectateID < 0 || SpectateID >= MAX_CLIENTS || !m_apPlayers[SpectateID] || m_apPlayers[SpectateID]->GetTeam() == TEAM_SPECTATORS)
  5157. +
  5158.                         {
  5159.                                 SendChatTarget(ClientID, "Invalid client id to move");
  5160.                                 return;
  5161. @@ -762,8 +894,8 @@
  5162.  
  5163.                         str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to move '%s' to spectators (%s)", Server()->ClientName(ClientID), Server()->ClientName(SpectateID), pReason);
  5164.                         str_format(aDesc, sizeof(aDesc), "move '%s' to spectators", Server()->ClientName(SpectateID));
  5165. +
  5166.                         str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, g_Config.m_SvVoteSpectateRejoindelay);
  5167. -                       m_VoteClientID = SpectateID;
  5168.                 }
  5169.  
  5170.                 if(aCmd[0])
  5171. @@ -792,7 +924,7 @@
  5172.                         m_VoteUpdate = true;
  5173.                 }
  5174.         }
  5175. -       else if(MsgID == NETMSGTYPE_CL_SETTEAM && m_pController->IsTeamChangeAllowed())
  5176. +       else if (MsgID == NETMSGTYPE_CL_SETTEAM && !m_World.m_Paused)
  5177.         {
  5178.                 CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg;
  5179.  
  5180. @@ -824,7 +956,8 @@
  5181.                                 pPlayer->m_LastSetTeam = Server()->Tick();
  5182.                                 if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS)
  5183.                                         m_VoteUpdate = true;
  5184. -                               m_pController->DoTeamChange(pPlayer, pMsg->m_Team);
  5185. +                               pPlayer->SetTeam(pMsg->m_Team);
  5186. +                               (void)m_pController->CheckTeamBalance();
  5187.                                 pPlayer->m_TeamChangeTick = Server()->Tick();
  5188.                         }
  5189.                         else
  5190. @@ -841,16 +974,23 @@
  5191.         {
  5192.                 CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg;
  5193.  
  5194. -               if(g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick())
  5195. +               if(pMsg->m_SpectatorID != SPEC_FREEVIEW)
  5196. +                       if (!Server()->ReverseTranslate(pMsg->m_SpectatorID, ClientID))
  5197. +                               return;
  5198. +
  5199. +               if(pPlayer->GetTeam() != TEAM_SPECTATORS || pPlayer->m_SpectatorID == pMsg->m_SpectatorID || ClientID == pMsg->m_SpectatorID ||
  5200. +                       (g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick()))
  5201.                         return;
  5202.  
  5203.                 pPlayer->m_LastSetSpectatorMode = Server()->Tick();
  5204. -               if(!pPlayer->SetSpectatorID(pMsg->m_SpectatorID))
  5205. +               if(pMsg->m_SpectatorID != SPEC_FREEVIEW && (!m_apPlayers[pMsg->m_SpectatorID] || m_apPlayers[pMsg->m_SpectatorID]->GetTeam() == TEAM_SPECTATORS))
  5206.                         SendChatTarget(ClientID, "Invalid spectator id used");
  5207. +               else
  5208. +                       pPlayer->m_SpectatorID = pMsg->m_SpectatorID;
  5209.         }
  5210.         else if (MsgID == NETMSGTYPE_CL_STARTINFO)
  5211.         {
  5212. -               if(pPlayer->m_IsReadyToEnter)
  5213. +               if(pPlayer->m_IsReady)
  5214.                         return;
  5215.  
  5216.                 CNetMsg_Cl_StartInfo *pMsg = (CNetMsg_Cl_StartInfo *)pRawMsg;
  5217. @@ -861,9 +1001,17 @@
  5218.                 Server()->SetClientClan(ClientID, pMsg->m_pClan);
  5219.                 Server()->SetClientCountry(ClientID, pMsg->m_Country);
  5220.                 str_copy(pPlayer->m_TeeInfos.m_SkinName, pMsg->m_pSkin, sizeof(pPlayer->m_TeeInfos.m_SkinName));
  5221. -               pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
  5222. +               if (!pPlayer->forcecolor) {
  5223. +                      pPlayer->origusecustcolor=pMsg->m_UseCustomColor;
  5224. +                      pPlayer->origbodycolor=pMsg->m_ColorBody;
  5225. +                      pPlayer->origfeetcolor=pMsg->m_ColorFeet;
  5226. +               }
  5227. +               pPlayer->m_TeeInfos.m_UseCustomColor = (pPlayer->forcecolor)?1:pMsg->m_UseCustomColor;
  5228. +               pPlayer->m_TeeInfos.m_ColorBody = (pPlayer->forcecolor)?pPlayer->forcecolor:pMsg->m_ColorBody;
  5229. +               pPlayer->m_TeeInfos.m_ColorFeet = (pPlayer->forcecolor)?pPlayer->forcecolor:pMsg->m_ColorFeet;
  5230. +               /*pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
  5231.                 pPlayer->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody;
  5232. -               pPlayer->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;
  5233. +               pPlayer->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;*/
  5234.                 m_pController->OnPlayerInfoChange(pPlayer);
  5235.  
  5236.                 // send vote options
  5237. @@ -942,7 +1090,7 @@
  5238.                 SendTuningParams(ClientID);
  5239.  
  5240.                 // client is ready to enter
  5241. -               pPlayer->m_IsReadyToEnter = true;
  5242. +               pPlayer->m_IsReady = true;
  5243.                 CNetMsg_Sv_ReadyToEnter m;
  5244.                 Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID);
  5245.         }
  5246. @@ -975,13 +1123,50 @@
  5247.         else if (MsgID == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused)
  5248.         {
  5249.                 CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg;
  5250. -
  5251. -               if(g_Config.m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick())
  5252. +              
  5253. +               if(g_Config.m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*1 > Server()->Tick())
  5254.                         return;
  5255.  
  5256.                 pPlayer->m_LastEmote = Server()->Tick();
  5257.  
  5258.                 SendEmoticon(ClientID, pMsg->m_Emoticon);
  5259. +               CCharacter* pChr = pPlayer->GetCharacter();
  5260. +               if(pChr && pPlayer)
  5261. +               {
  5262. +                       switch(pMsg->m_Emoticon)
  5263. +                       {
  5264. +                       case EMOTICON_EXCLAMATION:
  5265. +                       case EMOTICON_GHOST:
  5266. +                       case EMOTICON_QUESTION:
  5267. +                       case EMOTICON_WTF:
  5268. +                                       pChr->SetEmoteType(EMOTE_SURPRISE);
  5269. +                                       break;
  5270. +                       case EMOTICON_DOTDOT:
  5271. +                       case EMOTICON_DROP:
  5272. +                       case EMOTICON_ZZZ:
  5273. +                                       pChr->SetEmoteType(EMOTE_BLINK);
  5274. +                                       break;
  5275. +                       case EMOTICON_EYES:
  5276. +                       case EMOTICON_HEARTS:
  5277. +                       case EMOTICON_MUSIC:
  5278. +                                       pChr->SetEmoteType(EMOTE_HAPPY);
  5279. +                                       break;
  5280. +                       case EMOTICON_OOP:
  5281. +                       case EMOTICON_SORRY:
  5282. +                       case EMOTICON_SUSHI:
  5283. +                                       pChr->SetEmoteType(EMOTE_PAIN);
  5284. +                                       break;
  5285. +                       case EMOTICON_DEVILTEE:
  5286. +                       case EMOTICON_SPLATTEE:
  5287. +                       case EMOTICON_ZOMG:
  5288. +                                       pChr->SetEmoteType(EMOTE_ANGRY);
  5289. +                                       break;
  5290. +                               default:
  5291. +                                       break;
  5292. +                       }
  5293. +                       pChr->SetEmoteStop(Server()->Tick() + 2 * Server()->TickSpeed());
  5294. +      
  5295. +               }
  5296.         }
  5297.         else if (MsgID == NETMSGTYPE_CL_KILL && !m_World.m_Paused)
  5298.         {
  5299. @@ -991,14 +1176,6 @@
  5300.                 pPlayer->m_LastKill = Server()->Tick();
  5301.                 pPlayer->KillCharacter(WEAPON_SELF);
  5302.         }
  5303. -       else if (MsgID == NETMSGTYPE_CL_READYCHANGE)
  5304. -       {
  5305. -               if(pPlayer->m_LastReadyChange && pPlayer->m_LastReadyChange+Server()->TickSpeed()*1 > Server()->Tick())
  5306. -                       return;
  5307. -
  5308. -               pPlayer->m_LastReadyChange = Server()->Tick();
  5309. -               m_pController->OnPlayerReadyChange(pPlayer);
  5310. -       }
  5311.  }
  5312.  
  5313.  void CGameContext::ConTuneParam(IConsole::IResult *pResult, void *pUserData)
  5314. @@ -1044,10 +1221,10 @@
  5315.  {
  5316.         CGameContext *pSelf = (CGameContext *)pUserData;
  5317.  
  5318. -       if(pResult->NumArguments())
  5319. -               pSelf->m_pController->DoPause(clamp(pResult->GetInteger(0), -1, 1000));
  5320. -       else
  5321. -               pSelf->m_pController->DoPause(pSelf->m_pController->IsGamePaused() ? 0 : IGameController::TIMER_INFINITE);
  5322. +       if(pSelf->m_pController->IsGameOver())
  5323. +               return;
  5324. +
  5325. +       pSelf->m_World.m_Paused ^= 1;
  5326.  }
  5327.  
  5328.  void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData)
  5329. @@ -1060,9 +1237,9 @@
  5330.  {
  5331.         CGameContext *pSelf = (CGameContext *)pUserData;
  5332.         if(pResult->NumArguments())
  5333. -               pSelf->m_pController->DoWarmup(clamp(pResult->GetInteger(0), -1, 1000));
  5334. +               pSelf->m_pController->DoWarmup(pResult->GetInteger(0));
  5335.         else
  5336. -               pSelf->m_pController->DoWarmup(0);
  5337. +               pSelf->m_pController->StartRound();
  5338.  }
  5339.  
  5340.  void CGameContext::ConBroadcast(IConsole::IResult *pResult, void *pUserData)
  5341. @@ -1091,7 +1268,8 @@
  5342.         pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
  5343.  
  5344.         pSelf->m_apPlayers[ClientID]->m_TeamChangeTick = pSelf->Server()->Tick()+pSelf->Server()->TickSpeed()*Delay*60;
  5345. -       pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[ClientID], Team);
  5346. +       pSelf->m_apPlayers[ClientID]->SetTeam(Team);
  5347. +       (void)pSelf->m_pController->CheckTeamBalance();
  5348.  }
  5349.  
  5350.  void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData)
  5351. @@ -1105,7 +1283,9 @@
  5352.  
  5353.         for(int i = 0; i < MAX_CLIENTS; ++i)
  5354.                 if(pSelf->m_apPlayers[i])
  5355. -                       pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], Team, false);
  5356. +                       pSelf->m_apPlayers[i]->SetTeam(Team, false);
  5357. +
  5358. +       (void)pSelf->m_pController->CheckTeamBalance();
  5359.  }
  5360.  
  5361.  void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData)
  5362. @@ -1120,29 +1300,41 @@
  5363.         if(!pSelf->m_pController->IsTeamplay())
  5364.                 return;
  5365.  
  5366. -       int rnd = 0;
  5367. +       int CounterRed = 0;
  5368. +       int CounterBlue = 0;
  5369.         int PlayerTeam = 0;
  5370. -       int aPlayer[MAX_CLIENTS];
  5371. -
  5372. -       for(int i = 0; i < MAX_CLIENTS; i++)
  5373. +       for(int i = 0; i < MAX_CLIENTS; ++i)
  5374.                 if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  5375. -                       aPlayer[PlayerTeam++]=i;
  5376. -
  5377. +                       ++PlayerTeam;
  5378. +       PlayerTeam = (PlayerTeam+1)/2;
  5379. +      
  5380.         pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were shuffled");
  5381.  
  5382. -       //creating random permutation
  5383. -       for(int i = PlayerTeam; i > 1; i--)
  5384. +       for(int i = 0; i < MAX_CLIENTS; ++i)
  5385.         {
  5386. -               rnd = rand() % i;
  5387. -               int tmp = aPlayer[rnd];
  5388. -               aPlayer[rnd] = aPlayer[i-1];
  5389. -               aPlayer[i-1] = tmp;
  5390. +               if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  5391. +               {
  5392. +                       if(CounterRed == PlayerTeam)
  5393. +                               pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
  5394. +                       else if(CounterBlue == PlayerTeam)
  5395. +                               pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
  5396. +                       else
  5397. +                       {      
  5398. +                               if(rand() % 2)
  5399. +                               {
  5400. +                                       pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
  5401. +                                       ++CounterBlue;
  5402. +                               }
  5403. +                               else
  5404. +                               {
  5405. +                                       pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
  5406. +                                       ++CounterRed;
  5407. +                               }
  5408. +                       }
  5409. +               }
  5410.         }
  5411. -       //uneven Number of Players?
  5412. -       rnd = PlayerTeam % 2 ? rand() % 2 : 0;
  5413.  
  5414. -       for(int i = 0; i < PlayerTeam; i++)
  5415. -               pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[aPlayer[i]], i < (PlayerTeam+rnd)/2 ? TEAM_RED : TEAM_BLUE, false);
  5416. +       (void)pSelf->m_pController->CheckTeamBalance();
  5417.  }
  5418.  
  5419.  void CGameContext::ConLockTeams(IConsole::IResult *pResult, void *pUserData)
  5420. @@ -1323,6 +1515,7 @@
  5421.         else if(str_comp_nocase(pType, "kick") == 0)
  5422.         {
  5423.                 int KickID = str_toint(pValue);
  5424. +               //Server()->ReverseTranslate(KickID, ClientID);
  5425.                 if(KickID < 0 || KickID >= MAX_CLIENTS || !pSelf->m_apPlayers[KickID])
  5426.                 {
  5427.                         pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to kick");
  5428. @@ -1345,6 +1538,7 @@
  5429.         else if(str_comp_nocase(pType, "spectate") == 0)
  5430.         {
  5431.                 int SpectateID = str_toint(pValue);
  5432. +               //Server()->ReverseTranslate(SpectateID, ClientID);
  5433.                 if(SpectateID < 0 || SpectateID >= MAX_CLIENTS || !pSelf->m_apPlayers[SpectateID] || pSelf->m_apPlayers[SpectateID]->GetTeam() == TEAM_SPECTATORS)
  5434.                 {
  5435.                         pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to move");
  5436. @@ -1413,7 +1607,7 @@
  5437.         Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning");
  5438.         Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning");
  5439.  
  5440. -       Console()->Register("pause", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConPause, this, "Pause/unpause game");
  5441. +       Console()->Register("pause", "", CFGFLAG_SERVER, ConPause, this, "Pause/unpause game");
  5442.         Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map");
  5443.         Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)");
  5444.         Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message");
  5445. @@ -1433,37 +1627,53 @@
  5446.         Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
  5447.  }
  5448.  
  5449. -void CGameContext::OnInit()
  5450. +void CGameContext::OnInit(/*class IKernel *pKernel*/)
  5451.  {
  5452. -       // init everything
  5453.         m_pServer = Kernel()->RequestInterface<IServer>();
  5454.         m_pConsole = Kernel()->RequestInterface<IConsole>();
  5455.         m_World.SetGameServer(this);
  5456.         m_Events.SetGameServer(this);
  5457.  
  5458. +       //if(!data) // only load once
  5459. +               //data = load_data_from_memory(internal_data);
  5460. +
  5461.         for(int i = 0; i < NUM_NETOBJTYPES; i++)
  5462.                 Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
  5463.  
  5464.         m_Layers.Init(Kernel());
  5465.         m_Collision.Init(&m_Layers);
  5466.  
  5467. +       // reset everything here
  5468. +       //world = new GAMEWORLD;
  5469. +       //players = new CPlayer[MAX_CLIENTS];
  5470. +
  5471.         // select gametype
  5472. -       if(str_comp_nocase(g_Config.m_SvGametype, "mod") == 0)
  5473. +       if(str_comp(g_Config.m_SvGametype, "mod") == 0)
  5474.                 m_pController = new CGameControllerMOD(this);
  5475. -       else if(str_comp_nocase(g_Config.m_SvGametype, "ctf") == 0)
  5476. +       else if(str_comp(g_Config.m_SvGametype, "ctf") == 0)
  5477.                 m_pController = new CGameControllerCTF(this);
  5478. -       else if(str_comp_nocase(g_Config.m_SvGametype, "lms") == 0)
  5479. -               m_pController = new CGameControllerLMS(this);
  5480. -       else if(str_comp_nocase(g_Config.m_SvGametype, "sur") == 0)
  5481. -               m_pController = new CGameControllerSUR(this);
  5482. -       else if(str_comp_nocase(g_Config.m_SvGametype, "tdm") == 0)
  5483. +       else if(str_comp(g_Config.m_SvGametype, "tdm") == 0)
  5484.                 m_pController = new CGameControllerTDM(this);
  5485.         else
  5486.                 m_pController = new CGameControllerDM(this);
  5487.  
  5488. +       // setup core world
  5489. +       //for(int i = 0; i < MAX_CLIENTS; i++)
  5490. +       //      game.players[i].core.world = &game.world.core;
  5491. +
  5492.         // create all entities from the game layer
  5493.         CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
  5494.         CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data);
  5495. +
  5496. +
  5497. +
  5498. +
  5499. +       /*
  5500. +       num_spawn_points[0] = 0;
  5501. +       num_spawn_points[1] = 0;
  5502. +       num_spawn_points[2] = 0;
  5503. +       */
  5504. +
  5505.         for(int y = 0; y < pTileMap->m_Height; y++)
  5506.         {
  5507.                 for(int x = 0; x < pTileMap->m_Width; x++)
  5508. @@ -1478,11 +1688,15 @@
  5509.                 }
  5510.         }
  5511.  
  5512. +       //game.world.insert_entity(game.Controller);
  5513. +
  5514.  #ifdef CONF_DEBUG
  5515.         if(g_Config.m_DbgDummies)
  5516.         {
  5517.                 for(int i = 0; i < g_Config.m_DbgDummies ; i++)
  5518. -                       OnClientConnected(MAX_CLIENTS-i-1, true);
  5519. +               {
  5520. +                       OnClientConnected(MAX_CLIENTS-i-1);
  5521. +               }
  5522.         }
  5523.  #endif
  5524.  }
  5525. @@ -1516,6 +1730,8 @@
  5526.                 if(m_apPlayers[i])
  5527.                         m_apPlayers[i]->Snap(ClientID);
  5528.         }
  5529. +       m_apPlayers[ClientID]->FakeSnap(ClientID);
  5530. +
  5531.  }
  5532.  void CGameContext::OnPreSnap() {}
  5533.  void CGameContext::OnPostSnap()
  5534. @@ -1525,7 +1741,7 @@
  5535.  
  5536.  bool CGameContext::IsClientReady(int ClientID)
  5537.  {
  5538. -       return m_apPlayers[ClientID] && m_apPlayers[ClientID]->m_IsReadyToEnter ? true : false;
  5539. +       return m_apPlayers[ClientID] && m_apPlayers[ClientID]->m_IsReady ? true : false;
  5540.  }
  5541.  
  5542.  bool CGameContext::IsClientPlayer(int ClientID)
  5543. @@ -1533,7 +1749,7 @@
  5544.         return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true;
  5545.  }
  5546.  
  5547. -const char *CGameContext::GameType() { return m_pController && m_pController->GetGameType() ? m_pController->GetGameType() : ""; }
  5548. +const char *CGameContext::GameType() { return m_pController && m_pController->m_pGameType ? m_pController->m_pGameType : ""; }
  5549.  const char *CGameContext::Version() { return GAME_VERSION; }
  5550.  const char *CGameContext::NetVersion() { return GAME_NETVERSION; }
  5551.  
  5552. diff -Naur ../teeworlds/src/game/server/gamecontext.h src/game/server/gamecontext.h
  5553. --- ../teeworlds/src/game/server/gamecontext.h  2012-06-26 16:53:53.392865827 +1000
  5554. +++ src/game/server/gamecontext.h       2012-07-08 19:45:34.537929011 +1000
  5555. @@ -3,15 +3,26 @@
  5556.  #ifndef GAME_SERVER_GAMECONTEXT_H
  5557.  #define GAME_SERVER_GAMECONTEXT_H
  5558.  
  5559. -#include <engine/console.h>
  5560.  #include <engine/server.h>
  5561. +#include <engine/console.h>
  5562. +#include <engine/shared/memheap.h>
  5563.  
  5564.  #include <game/layers.h>
  5565.  #include <game/voting.h>
  5566.  
  5567.  #include "eventhandler.h"
  5568. +#include "gamecontroller.h"
  5569.  #include "gameworld.h"
  5570. +#include "player.h"
  5571.  
  5572. +#ifdef _MSC_VER
  5573. +typedef __int32 int32_t;
  5574. +typedef unsigned __int32 uint32_t;
  5575. +typedef __int64 int64_t;
  5576. +typedef unsigned __int64 uint64_t;
  5577. +#else
  5578. +#include <stdint.h>
  5579. +#endif
  5580.  /*
  5581.         Tick
  5582.                 Game Context (CGameContext::tick)
  5583. @@ -41,7 +52,8 @@
  5584.         CCollision m_Collision;
  5585.         CNetObjHandler m_NetObjHandler;
  5586.         CTuningParams m_Tuning;
  5587. -
  5588. +    
  5589. +       static void ConPowerups(IConsole::IResult *pResult, void *pUserData);
  5590.         static void ConTuneParam(IConsole::IResult *pResult, void *pUserData);
  5591.         static void ConTuneReset(IConsole::IResult *pResult, void *pUserData);
  5592.         static void ConTuneDump(IConsole::IResult *pResult, void *pUserData);
  5593. @@ -49,9 +61,11 @@
  5594.         static void ConChangeMap(IConsole::IResult *pResult, void *pUserData);
  5595.         static void ConRestart(IConsole::IResult *pResult, void *pUserData);
  5596.         static void ConBroadcast(IConsole::IResult *pResult, void *pUserData);
  5597. +       static void ConEyeEmote(IConsole::IResult *pResult, void *pUserData);
  5598.         static void ConSay(IConsole::IResult *pResult, void *pUserData);
  5599.         static void ConSetTeam(IConsole::IResult *pResult, void *pUserData);
  5600.         static void ConSetTeamAll(IConsole::IResult *pResult, void *pUserData);
  5601. +       static void ConSpin(IConsole::IResult *pResult, void *pUserData);
  5602.         static void ConSwapTeams(IConsole::IResult *pResult, void *pUserData);
  5603.         static void ConShuffleTeams(IConsole::IResult *pResult, void *pUserData);
  5604.         static void ConLockTeams(IConsole::IResult *pResult, void *pUserData);
  5605. @@ -76,11 +90,18 @@
  5606.         ~CGameContext();
  5607.  
  5608.         void Clear();
  5609. -
  5610. +       static void SendChatResponse(const char *pLine, void *pUser);
  5611. +       static void SendChatResponseAll(const char *pLine, void *pUser);
  5612. +       struct ChatResponseInfo
  5613. +       {
  5614. +               CGameContext *m_GameContext;
  5615. +               int m_To;
  5616. +       };
  5617. +      
  5618.         CEventHandler m_Events;
  5619. -       class CPlayer *m_apPlayers[MAX_CLIENTS];
  5620. +       CPlayer *m_apPlayers[MAX_CLIENTS];
  5621.  
  5622. -       class IGameController *m_pController;
  5623. +       IGameController *m_pController;
  5624.         CGameWorld m_World;
  5625.  
  5626.         // helper functions
  5627. @@ -93,8 +114,7 @@
  5628.         void EndVote();
  5629.         void SendVoteSet(int ClientID);
  5630.         void SendVoteStatus(int ClientID, int Total, int Yes, int No);
  5631. -       void AbortVoteOnDisconnect(int ClientID);
  5632. -       void AbortVoteOnTeamChange(int ClientID);
  5633. +       void AbortVoteKickOnDisconnect(int ClientID);
  5634.  
  5635.         int m_VoteCreator;
  5636.         int64 m_VoteCloseTime;
  5637. @@ -103,7 +123,6 @@
  5638.         char m_aVoteDescription[VOTE_DESC_LENGTH];
  5639.         char m_aVoteCommand[VOTE_CMD_LENGTH];
  5640.         char m_aVoteReason[VOTE_REASON_LENGTH];
  5641. -       int m_VoteClientID;
  5642.         int m_NumVoteOptions;
  5643.         int m_VoteEnforce;
  5644.         enum
  5645. @@ -112,7 +131,7 @@
  5646.                 VOTE_ENFORCE_NO,
  5647.                 VOTE_ENFORCE_YES,
  5648.         };
  5649. -       class CHeap *m_pVoteOptionHeap;
  5650. +       CHeap *m_pVoteOptionHeap;
  5651.         CVoteOptionServer *m_pVoteOptionFirst;
  5652.         CVoteOptionServer *m_pVoteOptionLast;
  5653.  
  5654. @@ -122,7 +141,7 @@
  5655.         void CreateHammerHit(vec2 Pos);
  5656.         void CreatePlayerSpawn(vec2 Pos);
  5657.         void CreateDeath(vec2 Pos, int Who);
  5658. -       void CreateSound(vec2 Pos, int Sound, int Mask=-1);
  5659. +       void CreateSound(vec2 Pos, int Sound, int64_t Mask=-1);
  5660.         void CreateSoundGlobal(int Sound, int Target=-1);
  5661.  
  5662.  
  5663. @@ -158,12 +177,11 @@
  5664.         virtual void OnPreSnap();
  5665.         virtual void OnSnap(int ClientID);
  5666.         virtual void OnPostSnap();
  5667. -
  5668. +      
  5669. +    char * HandleArguments(char *pString);
  5670.         virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID);
  5671.  
  5672. -       virtual void OnClientConnected(int ClientID) { OnClientConnected(ClientID, false); }
  5673. -       void OnClientConnected(int ClientID, bool Dummy);
  5674. -       void OnClientTeamChange(int ClientID);
  5675. +       virtual void OnClientConnected(int ClientID);
  5676.         virtual void OnClientEnter(int ClientID);
  5677.         virtual void OnClientDrop(int ClientID, const char *pReason);
  5678.         virtual void OnClientDirectInput(int ClientID, void *pInput);
  5679. @@ -177,8 +195,8 @@
  5680.         virtual const char *NetVersion();
  5681.  };
  5682.  
  5683. -inline int CmaskAll() { return -1; }
  5684. -inline int CmaskOne(int ClientID) { return 1<<ClientID; }
  5685. -inline int CmaskAllExceptOne(int ClientID) { return 0x7fffffff^CmaskOne(ClientID); }
  5686. -inline bool CmaskIsSet(int Mask, int ClientID) { return (Mask&CmaskOne(ClientID)) != 0; }
  5687. +inline int64_t CmaskAll() { return -1LL; }
  5688. +inline int64_t CmaskOne(int ClientID) { return 1LL<<ClientID; }
  5689. +inline int64_t CmaskAllExceptOne(int ClientID) { return CmaskAll()^CmaskOne(ClientID); }
  5690. +inline bool CmaskIsSet(int64_t Mask, int ClientID) { return (Mask&CmaskOne(ClientID)) != 0; }
  5691.  #endif
  5692. diff -Naur ../teeworlds/src/game/server/gamecontroller.cpp src/game/server/gamecontroller.cpp
  5693. --- ../teeworlds/src/game/server/gamecontroller.cpp     2012-06-26 16:53:53.396862075 +1000
  5694. +++ src/game/server/gamecontroller.cpp  2012-07-08 20:05:59.422259393 +1000
  5695. @@ -1,805 +1,192 @@
  5696.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  5697.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  5698.  #include <engine/shared/config.h>
  5699. -
  5700.  #include <game/mapitems.h>
  5701.  
  5702. -#include "entities/character.h"
  5703. +#include <game/generated/protocol.h>
  5704. +
  5705.  #include "entities/pickup.h"
  5706. -#include "gamecontext.h"
  5707.  #include "gamecontroller.h"
  5708. -#include "player.h"
  5709. +#include "gamecontext.h"
  5710.  
  5711.  
  5712. -IGameController::IGameController(CGameContext *pGameServer)
  5713. +IGameController::IGameController(class CGameContext *pGameServer)
  5714.  {
  5715.         m_pGameServer = pGameServer;
  5716.         m_pServer = m_pGameServer->Server();
  5717. +       m_pGameType = "unknown";
  5718.  
  5719. -       // balancing
  5720. -       m_aTeamSize[TEAM_RED] = 0;
  5721. -       m_aTeamSize[TEAM_BLUE] = 0;
  5722. -       m_UnbalancedTick = TBALANCE_OK;
  5723. -
  5724. -       // game
  5725. -       m_GameState = IGS_GAME_RUNNING;
  5726. -       m_GameStateTimer = TIMER_INFINITE;
  5727. -       m_GameStartTick = Server()->Tick();
  5728. -       m_MatchCount = 0;
  5729. -       m_RoundCount = 0;
  5730. +       //
  5731. +       DoWarmup(g_Config.m_SvWarmup);
  5732. +       m_GameOverTick = -1;
  5733.         m_SuddenDeath = 0;
  5734. +       m_RoundStartTick = Server()->Tick();
  5735. +       m_RoundCount = 0;
  5736. +       m_GameFlags = 0;
  5737.         m_aTeamscore[TEAM_RED] = 0;
  5738.         m_aTeamscore[TEAM_BLUE] = 0;
  5739. -       if(g_Config.m_SvWarmup)
  5740. -               SetGameState(IGS_WARMUP_USER, g_Config.m_SvWarmup);
  5741. -       else
  5742. -               SetGameState(IGS_WARMUP_GAME, TIMER_INFINITE);
  5743. -
  5744. -       // info
  5745. -       m_GameFlags = 0;
  5746. -       m_pGameType = "unknown";
  5747. -
  5748. -       // map
  5749.         m_aMapWish[0] = 0;
  5750.  
  5751. -       // spawn
  5752. +       m_UnbalancedTick = -1;
  5753. +       m_ForceBalanced = false;
  5754. +
  5755.         m_aNumSpawnPoints[0] = 0;
  5756.         m_aNumSpawnPoints[1] = 0;
  5757.         m_aNumSpawnPoints[2] = 0;
  5758.  }
  5759.  
  5760. -//activity
  5761. -void IGameController::DoActivityCheck()
  5762. -{
  5763. -       if(g_Config.m_SvInactiveKickTime == 0)
  5764. -               return;
  5765. -
  5766. -       for(int i = 0; i < MAX_CLIENTS; ++i)
  5767. -       {
  5768. -               if(GameServer()->m_apPlayers[i] && !GameServer()->m_apPlayers[i]->IsDummy() && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS &&
  5769. -                       !Server()->IsAuthed(i) && (Server()->Tick() > GameServer()->m_apPlayers[i]->m_LastActionTick+g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60))
  5770. -               {
  5771. -                       switch(g_Config.m_SvInactiveKick)
  5772. -                       {
  5773. -                       case 0:
  5774. -                               {
  5775. -                                       // move player to spectator
  5776. -                                       DoTeamChange(GameServer()->m_apPlayers[i], TEAM_SPECTATORS);
  5777. -                               }
  5778. -                               break;
  5779. -                       case 1:
  5780. -                               {
  5781. -                                       // move player to spectator if the reserved slots aren't filled yet, kick him otherwise
  5782. -                                       int Spectators = 0;
  5783. -                                       for(int j = 0; j < MAX_CLIENTS; ++j)
  5784. -                                               if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS)
  5785. -                                                       ++Spectators;
  5786. -                                       if(Spectators >= g_Config.m_SvSpectatorSlots)
  5787. -                                               Server()->Kick(i, "Kicked for inactivity");
  5788. -                                       else
  5789. -                                               DoTeamChange(GameServer()->m_apPlayers[i], TEAM_SPECTATORS);
  5790. -                               }
  5791. -                               break;
  5792. -                       case 2:
  5793. -                               {
  5794. -                                       // kick the player
  5795. -                                       Server()->Kick(i, "Kicked for inactivity");
  5796. -                               }
  5797. -                       }
  5798. -               }
  5799. -       }
  5800. -}
  5801. -
  5802. -bool IGameController::GetPlayersReadyState()
  5803. +IGameController::~IGameController()
  5804.  {
  5805. -       for(int i = 0; i < MAX_CLIENTS; ++i)
  5806. -       {
  5807. -               if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && !GameServer()->m_apPlayers[i]->m_IsReadyToPlay)
  5808. -                       return false;
  5809. -       }
  5810. -
  5811. -       return true;
  5812.  }
  5813.  
  5814. -void IGameController::SetPlayersReadyState(bool ReadyState)
  5815. +float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos)
  5816.  {
  5817. -       for(int i = 0; i < MAX_CLIENTS; ++i)
  5818. +       float Score = 0.0f;
  5819. +       CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER));
  5820. +       for(; pC; pC = (CCharacter *)pC->TypeNext())
  5821.         {
  5822. -               if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && (ReadyState || !GameServer()->m_apPlayers[i]->m_DeadSpecMode))
  5823. -                       GameServer()->m_apPlayers[i]->m_IsReadyToPlay = ReadyState;
  5824. -       }
  5825. -}
  5826. -
  5827. -// balancing
  5828. -bool IGameController::CanBeMovedOnBalance(int ClientID) const
  5829. -{
  5830. -       return true;
  5831. -}
  5832. +               // team mates are not as dangerous as enemies
  5833. +               float Scoremod = 1.0f;
  5834. +               if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam)
  5835. +                       Scoremod = 0.5f;
  5836.  
  5837. -void IGameController::CheckTeamBalance()
  5838. -{
  5839. -       if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime)
  5840. -       {
  5841. -               m_UnbalancedTick = TBALANCE_OK;
  5842. -               return;
  5843. +               float d = distance(Pos, pC->m_Pos);
  5844. +               Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d);
  5845.         }
  5846.  
  5847. -       // check if teams are unbalanced
  5848. -       char aBuf[256];
  5849. -       if(absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) >= NUM_TEAMS)
  5850. -       {
  5851. -               str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE]);
  5852. -               if(m_UnbalancedTick <= TBALANCE_OK)
  5853. -                       m_UnbalancedTick = Server()->Tick();
  5854. -       }
  5855. -       else
  5856. -       {
  5857. -               str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE]);
  5858. -               m_UnbalancedTick = TBALANCE_OK;
  5859. -       }
  5860. -       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  5861. +       return Score;
  5862.  }
  5863.  
  5864. -void IGameController::DoTeamBalance()
  5865. +void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type)
  5866.  {
  5867. -       if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime || absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) < NUM_TEAMS)
  5868. -               return;
  5869. -
  5870. -       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams");
  5871. -
  5872. -       float aTeamScore[NUM_TEAMS] = {0};
  5873. -       float aPlayerScore[MAX_CLIENTS] = {0.0f};
  5874. -
  5875. -       // gather stats
  5876. -       for(int i = 0; i < MAX_CLIENTS; i++)
  5877. +       // get spawn point
  5878. +       for(int i = 0; i < m_aNumSpawnPoints[Type]; i++)
  5879.         {
  5880. -               if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  5881. +               // check if the position is occupado
  5882. +               CCharacter *aEnts[MAX_CLIENTS];
  5883. +               int Num = GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
  5884. +               vec2 Positions[5] = { vec2(0.0f, 0.0f), vec2(-32.0f, 0.0f), vec2(0.0f, -32.0f), vec2(32.0f, 0.0f), vec2(0.0f, 32.0f) }; // start, left, up, right, down
  5885. +               int Result = -1;
  5886. +               for(int Index = 0; Index < 5 && Result == -1; ++Index)
  5887.                 {
  5888. -                       aPlayerScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/
  5889. -                               (Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick);
  5890. -                       aTeamScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPlayerScore[i];
  5891. +                       Result = Index;
  5892. +                       for(int c = 0; c < Num; ++c)
  5893. +                               if(GameServer()->Collision()->CheckPoint(m_aaSpawnPoints[Type][i]+Positions[Index]) ||
  5894. +                                       distance(aEnts[c]->m_Pos, m_aaSpawnPoints[Type][i]+Positions[Index]) <= aEnts[c]->m_ProximityRadius)
  5895. +                               {
  5896. +                                       Result = -1;
  5897. +                                       break;
  5898. +                               }
  5899.                 }
  5900. -       }
  5901. -
  5902. -       int BiggerTeam = (m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE]) ? TEAM_RED : TEAM_BLUE;
  5903. -       int NumBalance = absolute(m_aTeamSize[TEAM_RED]-m_aTeamSize[TEAM_BLUE]) / NUM_TEAMS;
  5904. +               if(Result == -1)
  5905. +                       continue;       // try next spawn point
  5906.  
  5907. -       // balance teams
  5908. -       do
  5909. -       {
  5910. -               CPlayer *pPlayer = 0;
  5911. -               float ScoreDiff = aTeamScore[BiggerTeam];
  5912. -               for(int i = 0; i < MAX_CLIENTS; i++)
  5913. +               vec2 P = m_aaSpawnPoints[Type][i]+Positions[Result];
  5914. +               float S = EvaluateSpawnPos(pEval, P);
  5915. +               if(!pEval->m_Got || pEval->m_Score > S)
  5916.                 {
  5917. -                       if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i))
  5918. -                               continue;
  5919. -
  5920. -                       // remember the player whom would cause lowest score-difference
  5921. -                       if(GameServer()->m_apPlayers[i]->GetTeam() == BiggerTeam &&
  5922. -                               (!pPlayer || absolute((aTeamScore[BiggerTeam^1]+aPlayerScore[i]) - (aTeamScore[BiggerTeam]-aPlayerScore[i])) < ScoreDiff))
  5923. -                       {
  5924. -                               pPlayer = GameServer()->m_apPlayers[i];
  5925. -                               ScoreDiff = absolute((aTeamScore[BiggerTeam^1]+aPlayerScore[i]) - (aTeamScore[BiggerTeam]-aPlayerScore[i]));
  5926. -                       }
  5927. +                       pEval->m_Got = true;
  5928. +                       pEval->m_Score = S;
  5929. +                       pEval->m_Pos = P;
  5930.                 }
  5931. -
  5932. -               // move the player to the other team
  5933. -               int Temp = pPlayer->m_LastActionTick;
  5934. -               DoTeamChange(pPlayer, BiggerTeam^1);
  5935. -               pPlayer->m_LastActionTick = Temp;
  5936. -               pPlayer->Respawn();
  5937. -               char aBuf[128];
  5938. -               str_format(aBuf, sizeof(aBuf), "You were moved to %s due to team balancing", GetTeamName(pPlayer->GetTeam()));
  5939. -               GameServer()->SendBroadcast(aBuf, pPlayer->GetCID());
  5940.         }
  5941. -       while(--NumBalance);
  5942. -
  5943. -       m_UnbalancedTick = TBALANCE_OK;
  5944. -       GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
  5945.  }
  5946.  
  5947. -// event
  5948. -int IGameController::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int Weapon)
  5949. +bool IGameController::CanSpawn(int Team, vec2 *pOutPos)
  5950.  {
  5951. -       // do scoreing
  5952. -       if(!pKiller || Weapon == WEAPON_GAME)
  5953. -               return 0;
  5954. -       if(pKiller == pVictim->GetPlayer())
  5955. -               pVictim->GetPlayer()->m_Score--; // suicide
  5956. -       else
  5957. -       {
  5958. -               if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam())
  5959. -                       pKiller->m_Score--; // teamkill
  5960. -               else
  5961. -                       pKiller->m_Score++; // normal kill
  5962. -       }
  5963. -       if(Weapon == WEAPON_SELF)
  5964. -               pVictim->GetPlayer()->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()*3.0f;
  5965. -
  5966. -
  5967. -       // update spectator modes for dead players in survival
  5968. -       if(m_GameFlags&GAMEFLAG_SURVIVAL)
  5969. -       {
  5970. -               for(int i = 0; i < MAX_CLIENTS; ++i)
  5971. -                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_DeadSpecMode)
  5972. -                               GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
  5973. -       }
  5974. +       CSpawnEval Eval;
  5975.  
  5976. -       return 0;
  5977. -}
  5978. +       // spectators can't spawn
  5979. +       if(Team == TEAM_SPECTATORS)
  5980. +               return false;
  5981.  
  5982. -void IGameController::OnCharacterSpawn(CCharacter *pChr)
  5983. -{
  5984. -       if(m_GameFlags&GAMEFLAG_SURVIVAL)
  5985. +       if(IsTeamplay())
  5986.         {
  5987. -               // give start equipment
  5988. -               pChr->IncreaseHealth(10);
  5989. -               pChr->IncreaseArmor(5);
  5990. -
  5991. -               pChr->GiveWeapon(WEAPON_HAMMER, -1);
  5992. -               pChr->GiveWeapon(WEAPON_GUN, 10);
  5993. -               pChr->GiveWeapon(WEAPON_SHOTGUN, 10);
  5994. -               pChr->GiveWeapon(WEAPON_GRENADE, 10);
  5995. -               pChr->GiveWeapon(WEAPON_LASER, 5);
  5996. +               Eval.m_FriendlyTeam = Team;
  5997.  
  5998. -               // prevent respawn
  5999. -               pChr->GetPlayer()->m_RespawnDisabled = GetStartRespawnState();
  6000. +               // first try own team spawn, then normal spawn and then enemy
  6001. +               EvaluateSpawnType(&Eval, 1+(Team&1));
  6002. +               if(!Eval.m_Got)
  6003. +               {
  6004. +                       EvaluateSpawnType(&Eval, 0);
  6005. +                       if(!Eval.m_Got)
  6006. +                               EvaluateSpawnType(&Eval, 1+((Team+1)&1));
  6007. +               }
  6008.         }
  6009.         else
  6010.         {
  6011. -               // default health
  6012. -               pChr->IncreaseHealth(10);
  6013. -
  6014. -               // give default weapons
  6015. -               pChr->GiveWeapon(WEAPON_HAMMER, -1);
  6016. -               pChr->GiveWeapon(WEAPON_GUN, 10);
  6017. +               EvaluateSpawnType(&Eval, 0);
  6018. +               EvaluateSpawnType(&Eval, 1);
  6019. +               EvaluateSpawnType(&Eval, 2);
  6020.         }
  6021. +
  6022. +       *pOutPos = Eval.m_Pos;
  6023. +       return Eval.m_Got;
  6024.  }
  6025.  
  6026. +
  6027.  bool IGameController::OnEntity(int Index, vec2 Pos)
  6028.  {
  6029. -       // don't add pickups in survival
  6030. -       if(m_GameFlags&GAMEFLAG_SURVIVAL)
  6031. -       {
  6032. -               if(Index < ENTITY_SPAWN || Index > ENTITY_SPAWN_BLUE)
  6033. -                       return false;
  6034. -       }
  6035. -
  6036.         int Type = -1;
  6037. +       int SubType = 0;
  6038.  
  6039. -       switch(Index)
  6040. -       {
  6041. -       case ENTITY_SPAWN:
  6042. +       if(Index == ENTITY_SPAWN)
  6043.                 m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos;
  6044. -               break;
  6045. -       case ENTITY_SPAWN_RED:
  6046. +       else if(Index == ENTITY_SPAWN_RED)
  6047.                 m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos;
  6048. -               break;
  6049. -       case ENTITY_SPAWN_BLUE:
  6050. +       else if(Index == ENTITY_SPAWN_BLUE)
  6051.                 m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = Pos;
  6052. -               break;
  6053. -       case ENTITY_ARMOR_1:
  6054. -               Type = PICKUP_ARMOR;
  6055. -               break;
  6056. -       case ENTITY_HEALTH_1:
  6057. -               Type = PICKUP_HEALTH;
  6058. -               break;
  6059. -       case ENTITY_WEAPON_SHOTGUN:
  6060. -               Type = PICKUP_SHOTGUN;
  6061. -               break;
  6062. -       case ENTITY_WEAPON_GRENADE:
  6063. -               Type = PICKUP_GRENADE;
  6064. -               break;
  6065. -       case ENTITY_WEAPON_LASER:
  6066. -               Type = PICKUP_LASER;
  6067. -               break;
  6068. -       case ENTITY_POWERUP_NINJA:
  6069. -               if(g_Config.m_SvPowerups)
  6070. -                       Type = PICKUP_NINJA;
  6071. -       }
  6072. -
  6073. -       if(Type != -1)
  6074. -       {
  6075. -               CPickup *pPickup = new CPickup(&GameServer()->m_World, Type);
  6076. -               pPickup->m_Pos = Pos;
  6077. -               return true;
  6078. -       }
  6079. -
  6080. -       return false;
  6081. -}
  6082. -
  6083. -void IGameController::OnPlayerDisconnect(CPlayer *pPlayer, const char *pReason)
  6084. -{
  6085. -       pPlayer->OnDisconnect();
  6086. -
  6087. -       int ClientID = pPlayer->GetCID();
  6088. -       if(Server()->ClientIngame(ClientID))
  6089. -       {
  6090. -               char aBuf[512];
  6091. -               if(pReason && *pReason)
  6092. -                       str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(ClientID), pReason);
  6093. -               else
  6094. -                       str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(ClientID));
  6095. -               GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  6096. -
  6097. -               str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", ClientID, Server()->ClientName(ClientID));
  6098. -               GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "game", aBuf);
  6099. -       }
  6100. -
  6101. -       if(pPlayer->GetTeam() != TEAM_SPECTATORS)
  6102. -       {
  6103. -               --m_aTeamSize[pPlayer->GetTeam()];
  6104. -               m_UnbalancedTick = TBALANCE_CHECK;
  6105. -       }
  6106. -}
  6107. -
  6108. -void IGameController::OnPlayerInfoChange(CPlayer *pPlayer)
  6109. -{
  6110. -       const int aTeamColors[2] = {65387, 10223467};
  6111. -       if(IsTeamplay())
  6112. -       {
  6113. -               pPlayer->m_TeeInfos.m_UseCustomColor = 1;
  6114. -               if(pPlayer->GetTeam() >= TEAM_RED && pPlayer->GetTeam() <= TEAM_BLUE)
  6115. -               {
  6116. -                       pPlayer->m_TeeInfos.m_ColorBody = aTeamColors[pPlayer->GetTeam()];
  6117. -                       pPlayer->m_TeeInfos.m_ColorFeet = aTeamColors[pPlayer->GetTeam()];
  6118. -               }
  6119. -               else
  6120. -               {
  6121. -                       pPlayer->m_TeeInfos.m_ColorBody = 12895054;
  6122. -                       pPlayer->m_TeeInfos.m_ColorFeet = 12895054;
  6123. -               }
  6124. -       }
  6125. -}
  6126. -
  6127. -void IGameController::OnPlayerReadyChange(CPlayer *pPlayer)
  6128. -{
  6129. -       if(g_Config.m_SvPlayerReadyMode && pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_DeadSpecMode)
  6130. +       else if(Index == ENTITY_ARMOR_1)
  6131. +               Type = POWERUP_ARMOR;
  6132. +       else if(Index == ENTITY_HEALTH_1)
  6133. +               Type = POWERUP_HEALTH;
  6134. +       else if(Index == ENTITY_WEAPON_SHOTGUN)
  6135.         {
  6136. -               // change players ready state
  6137. -               pPlayer->m_IsReadyToPlay ^= 1;
  6138. -
  6139. -               // check if it effects current game state
  6140. -               switch(m_GameState)
  6141. -               {
  6142. -               case IGS_GAME_RUNNING:
  6143. -                       // one player isn't ready -> pause the game
  6144. -                       if(!pPlayer->m_IsReadyToPlay)
  6145. -                               SetGameState(IGS_GAME_PAUSED, TIMER_INFINITE);
  6146. -                       break;
  6147. -               case IGS_WARMUP_USER:
  6148. -                       // all players are ready -> end warmup
  6149. -                       if(GetPlayersReadyState())
  6150. -                               SetGameState(IGS_WARMUP_USER, 0);
  6151. -                       break;
  6152. -               case IGS_GAME_PAUSED:
  6153. -                       // all players are ready -> unpause the game
  6154. -                       if(GetPlayersReadyState())
  6155. -                               SetGameState(IGS_GAME_PAUSED, 0);
  6156. -                       break;
  6157. -               case IGS_WARMUP_GAME:
  6158. -               case IGS_START_COUNTDOWN:
  6159. -               case IGS_END_MATCH:
  6160. -               case IGS_END_ROUND:
  6161. -                       // not effected
  6162. -                       break;
  6163. -               }
  6164. +               Type = POWERUP_WEAPON;
  6165. +               SubType = WEAPON_SHOTGUN;
  6166.         }
  6167. -}
  6168. -
  6169. -void IGameController::OnReset()
  6170. -{
  6171. -       for(int i = 0; i < MAX_CLIENTS; i++)
  6172. +       else if(Index == ENTITY_WEAPON_GRENADE)
  6173.         {
  6174. -               if(GameServer()->m_apPlayers[i])
  6175. -               {
  6176. -                       GameServer()->m_apPlayers[i]->m_RespawnDisabled = false;
  6177. -                       GameServer()->m_apPlayers[i]->Respawn();
  6178. -                       GameServer()->m_apPlayers[i]->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  6179. -                       if(m_RoundCount == 0)
  6180. -                       {
  6181. -                               GameServer()->m_apPlayers[i]->m_Score = 0;
  6182. -                               GameServer()->m_apPlayers[i]->m_ScoreStartTick = Server()->Tick();
  6183. -                       }
  6184. -                       GameServer()->m_apPlayers[i]->m_IsReadyToPlay = true;
  6185. -               }
  6186. +               Type = POWERUP_WEAPON;
  6187. +               SubType = WEAPON_GRENADE;
  6188.         }
  6189. -}
  6190. -
  6191. -// game
  6192. -void IGameController::DoWincheckMatch()
  6193. -{
  6194. -       if(IsTeamplay())
  6195. +       else if(Index == ENTITY_WEAPON_RIFLE)
  6196.         {
  6197. -               // check score win condition
  6198. -               if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
  6199. -                       (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  6200. -               {
  6201. -                       if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE] || m_GameFlags&GAMEFLAG_SURVIVAL)
  6202. -                               EndMatch();
  6203. -                       else
  6204. -                               m_SuddenDeath = 1;
  6205. -               }
  6206. +               Type = POWERUP_WEAPON;
  6207. +               SubType = WEAPON_RIFLE;
  6208.         }
  6209. -       else
  6210. +       else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups)
  6211.         {
  6212. -               // gather some stats
  6213. -               int Topscore = 0;
  6214. -               int TopscoreCount = 0;
  6215. -               for(int i = 0; i < MAX_CLIENTS; i++)
  6216. -               {
  6217. -                       if(GameServer()->m_apPlayers[i])
  6218. -                       {
  6219. -                               if(GameServer()->m_apPlayers[i]->m_Score > Topscore)
  6220. -                               {
  6221. -                                       Topscore = GameServer()->m_apPlayers[i]->m_Score;
  6222. -                                       TopscoreCount = 1;
  6223. -                               }
  6224. -                               else if(GameServer()->m_apPlayers[i]->m_Score == Topscore)
  6225. -                                       TopscoreCount++;
  6226. -                       }
  6227. -               }
  6228. -
  6229. -               // check score win condition
  6230. -               if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) ||
  6231. -                       (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  6232. -               {
  6233. -                       if(TopscoreCount == 1)
  6234. -                               EndMatch();
  6235. -                       else
  6236. -                               m_SuddenDeath = 1;
  6237. -               }
  6238. +               Type = POWERUP_NINJA;
  6239. +               SubType = WEAPON_NINJA;
  6240.         }
  6241. -}
  6242. -
  6243. -void IGameController::ResetGame()
  6244. -{
  6245. -       // reset the game
  6246. -       GameServer()->m_World.m_ResetRequested = true;
  6247. -      
  6248. -       SetGameState(IGS_GAME_RUNNING);
  6249. -       m_GameStartTick = Server()->Tick();
  6250. -       m_SuddenDeath = 0;
  6251. -
  6252. -       // do team-balancing
  6253. -       DoTeamBalance();
  6254. -}
  6255.  
  6256. -void IGameController::SetGameState(EGameState GameState, int Timer)
  6257. -{
  6258. -       // change game state
  6259. -       switch(GameState)
  6260. +       if(Type != -1)
  6261.         {
  6262. -       case IGS_WARMUP_GAME:
  6263. -               // game based warmup is only possible when game or any warmup is running
  6264. -               if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER)
  6265. -               {
  6266. -                       if(Timer == TIMER_INFINITE)
  6267. -                       {
  6268. -                               // run warmup till there're enough players
  6269. -                               m_GameState = GameState;
  6270. -                               m_GameStateTimer = TIMER_INFINITE;
  6271. -              
  6272. -                               // enable respawning in survival when activating warmup
  6273. -                               if(m_GameFlags&GAMEFLAG_SURVIVAL)
  6274. -                               {
  6275. -                                       for(int i = 0; i < MAX_CLIENTS; ++i)
  6276. -                                               if(GameServer()->m_apPlayers[i])
  6277. -                                                       GameServer()->m_apPlayers[i]->m_RespawnDisabled = false;
  6278. -                               }
  6279. -                       }
  6280. -                       else if(Timer == 0)
  6281. -                       {
  6282. -                               // start new match
  6283. -                               StartMatch();
  6284. -                       }
  6285. -               }
  6286. -               break;
  6287. -       case IGS_WARMUP_USER:
  6288. -               // user based warmup is only possible when the game or a user based warmup is running
  6289. -               if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_WARMUP_USER)
  6290. -               {
  6291. -                       if(Timer != 0)
  6292. -                       {
  6293. -                               // start warmup
  6294. -                               if(Timer < 0 && g_Config.m_SvPlayerReadyMode)
  6295. -                               {
  6296. -                                       // run warmup till all players are ready
  6297. -                                       m_GameState = GameState;
  6298. -                                       m_GameStateTimer = TIMER_INFINITE;
  6299. -                                       SetPlayersReadyState(false);
  6300. -                               }
  6301. -                               else if(Timer > 0)
  6302. -                               {
  6303. -                                       // run warmup for a specific time intervall
  6304. -                                       m_GameState = GameState;
  6305. -                                       m_GameStateTimer = Timer*Server()->TickSpeed();
  6306. -                               }
  6307. -              
  6308. -                               // enable respawning in survival when activating warmup
  6309. -                               if(m_GameFlags&GAMEFLAG_SURVIVAL)
  6310. -                               {
  6311. -                                       for(int i = 0; i < MAX_CLIENTS; ++i)
  6312. -                                               if(GameServer()->m_apPlayers[i])
  6313. -                                                       GameServer()->m_apPlayers[i]->m_RespawnDisabled = false;
  6314. -                               }
  6315. -                       }
  6316. -                       else
  6317. -                       {
  6318. -                               // start new match
  6319. -                               StartMatch();
  6320. -                       }
  6321. -               }
  6322. -               break;
  6323. -       case IGS_START_COUNTDOWN:
  6324. -               // only possible when game, pause or start countdown is running
  6325. -               if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_START_COUNTDOWN)
  6326. -               {
  6327. -                       m_GameState = GameState;
  6328. -                       m_GameStateTimer = 3*Server()->TickSpeed();
  6329. -                       GameServer()->m_World.m_Paused = true;
  6330. -               }
  6331. -               break;
  6332. -       case IGS_GAME_RUNNING:
  6333. -               // always possible
  6334. -               {
  6335. -                       m_GameState = GameState;
  6336. -                       m_GameStateTimer = TIMER_INFINITE;
  6337. -                       SetPlayersReadyState(true);
  6338. -                       GameServer()->m_World.m_Paused = false;
  6339. -               }
  6340. -               break;
  6341. -       case IGS_GAME_PAUSED:
  6342. -               // only possible when game is running or paused
  6343. -               if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_GAME_PAUSED)
  6344. -               {
  6345. -                       if(Timer != 0)
  6346. -                       {
  6347. -                               // start pause
  6348. -                               if(Timer < 0)
  6349. -                               {
  6350. -                                       // pauses infinitely till all players are ready or disabled via rcon command
  6351. -                                       m_GameStateTimer = TIMER_INFINITE;
  6352. -                                       SetPlayersReadyState(false);
  6353. -                               }
  6354. -                               else
  6355. -                               {
  6356. -                                       // pauses for a specific time intervall
  6357. -                                       m_GameStateTimer = Timer*Server()->TickSpeed();
  6358. -                               }
  6359. -
  6360. -                               m_GameState = GameState;
  6361. -                               GameServer()->m_World.m_Paused = true;
  6362. -                       }
  6363. -                       else
  6364. -                       {
  6365. -                               // start a countdown to end pause
  6366. -                               SetGameState(IGS_START_COUNTDOWN);
  6367. -                       }
  6368. -               }
  6369. -               break;
  6370. -       case IGS_END_ROUND:
  6371. -       case IGS_END_MATCH:
  6372. -               // only possible when game is running or over
  6373. -               if(m_GameState == IGS_GAME_RUNNING || m_GameState == IGS_END_MATCH || m_GameState == IGS_END_ROUND)
  6374. -               {
  6375. -                       m_GameState = GameState;
  6376. -                       m_GameStateTimer = Timer*Server()->TickSpeed();
  6377. -                       m_SuddenDeath = 0;
  6378. -                       GameServer()->m_World.m_Paused = true;
  6379. -               }
  6380. +               CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType);
  6381. +               pPickup->m_Pos = Pos;
  6382. +               return true;
  6383.         }
  6384. -}
  6385. -
  6386. -void IGameController::StartMatch()
  6387. -{
  6388. -       ResetGame();
  6389. -
  6390. -       m_RoundCount = 0;
  6391. -       m_aTeamscore[TEAM_RED] = 0;
  6392. -       m_aTeamscore[TEAM_BLUE] = 0;
  6393. -
  6394. -       // start countdown if there're enough players, otherwise do warmup till there're
  6395. -       if(HasEnoughPlayers())
  6396. -               SetGameState(IGS_START_COUNTDOWN);
  6397. -       else
  6398. -               SetGameState(IGS_WARMUP_GAME, TIMER_INFINITE);
  6399. -
  6400. -       Server()->DemoRecorder_HandleAutoStart();
  6401. -       char aBuf[256];
  6402. -       str_format(aBuf, sizeof(aBuf), "start match type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS);
  6403. -       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  6404. -}
  6405. -
  6406. -void IGameController::StartRound()
  6407. -{
  6408. -       ResetGame();
  6409. -
  6410. -       ++m_RoundCount;
  6411.  
  6412. -       // start countdown if there're enough players, otherwise abort to warmup
  6413. -       if(HasEnoughPlayers())
  6414. -               SetGameState(IGS_START_COUNTDOWN);
  6415. -       else
  6416. -               SetGameState(IGS_WARMUP_GAME, TIMER_INFINITE);
  6417. +       return false;
  6418.  }
  6419.  
  6420. -// general
  6421. -void IGameController::Snap(int SnappingClient)
  6422. +void IGameController::EndRound()
  6423.  {
  6424. -       CNetObj_GameInfo *pGameInfoObj = (CNetObj_GameInfo *)Server()->SnapNewItem(NETOBJTYPE_GAMEINFO, 0, sizeof(CNetObj_GameInfo));
  6425. -       if(!pGameInfoObj)
  6426. +       if(m_Warmup) // game can't end when we are running warmup
  6427.                 return;
  6428.  
  6429. -       pGameInfoObj->m_GameFlags = m_GameFlags;
  6430. -
  6431. -       pGameInfoObj->m_GameStateFlags = 0;
  6432. -       pGameInfoObj->m_GameStateTimer = 0;
  6433. -       switch(m_GameState)
  6434. -       {
  6435. -       case IGS_WARMUP_GAME:
  6436. -       case IGS_WARMUP_USER:
  6437. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_WARMUP;
  6438. -               pGameInfoObj->m_GameStateTimer = m_GameStateTimer;
  6439. -               break;
  6440. -       case IGS_START_COUNTDOWN:
  6441. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED;
  6442. -               pGameInfoObj->m_GameStateTimer = m_GameStateTimer;
  6443. -               break;
  6444. -       case IGS_GAME_PAUSED:
  6445. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_PAUSED;
  6446. -               pGameInfoObj->m_GameStateTimer = m_GameStateTimer;
  6447. -               break;
  6448. -       case IGS_END_ROUND:
  6449. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_ROUNDOVER;
  6450. -               pGameInfoObj->m_GameStateTimer = Server()->Tick()-m_GameStartTick-10*Server()->TickSpeed()+m_GameStateTimer;
  6451. -               break;
  6452. -       case IGS_END_MATCH:
  6453. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_GAMEOVER;
  6454. -               pGameInfoObj->m_GameStateTimer = Server()->Tick()-m_GameStartTick-10*Server()->TickSpeed()+m_GameStateTimer;
  6455. -               break;
  6456. -       case IGS_GAME_RUNNING:
  6457. -               // not effected
  6458. -               break;
  6459. -       }
  6460. -       if(m_SuddenDeath)
  6461. -               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_SUDDENDEATH;
  6462. -
  6463. -       pGameInfoObj->m_GameStartTick = m_GameStartTick;
  6464. -
  6465. -       pGameInfoObj->m_ScoreLimit = g_Config.m_SvScorelimit;
  6466. -       pGameInfoObj->m_TimeLimit = g_Config.m_SvTimelimit;
  6467. -
  6468. -       pGameInfoObj->m_MatchNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvMatchesPerMap) ? g_Config.m_SvMatchesPerMap : 0;
  6469. -       pGameInfoObj->m_MatchCurrent = m_MatchCount+1;
  6470. -}
  6471. -
  6472. -void IGameController::Tick()
  6473. -{
  6474. -       // handle game states
  6475. -       if(m_GameState != IGS_GAME_RUNNING)
  6476. -       {
  6477. -               if(m_GameStateTimer > 0)
  6478. -                       --m_GameStateTimer;
  6479. -
  6480. -               if(m_GameStateTimer == 0)
  6481. -               {
  6482. -                       // timer fires
  6483. -                       switch(m_GameState)
  6484. -                       {
  6485. -                       case IGS_WARMUP_USER:
  6486. -                               // end warmup
  6487. -                               SetGameState(IGS_WARMUP_USER, 0);
  6488. -                               break;
  6489. -                       case IGS_START_COUNTDOWN:
  6490. -                               // unpause the game
  6491. -                               SetGameState(IGS_GAME_RUNNING);
  6492. -                               break;
  6493. -                       case IGS_GAME_PAUSED:
  6494. -                               // end pause
  6495. -                               SetGameState(IGS_GAME_PAUSED, 0);
  6496. -                               break;
  6497. -                       case IGS_END_ROUND:
  6498. -                               // check if the match is over otherwise start next round
  6499. -                               DoWincheckMatch();
  6500. -                               if(m_GameState != IGS_END_MATCH)
  6501. -                                       StartRound();
  6502. -                               break;
  6503. -                       case IGS_END_MATCH:
  6504. -                               // start next match
  6505. -                               CycleMap();
  6506. -                               StartMatch();
  6507. -                               m_MatchCount++;
  6508. -                               break;
  6509. -                       case IGS_WARMUP_GAME:
  6510. -                       case IGS_GAME_RUNNING:
  6511. -                               // not effected
  6512. -                               break;
  6513. -                       }
  6514. -               }
  6515. -               else
  6516. -               {
  6517. -                       // timer still running
  6518. -                       switch(m_GameState)
  6519. -                       {
  6520. -                       case IGS_WARMUP_USER:
  6521. -                               // check if player ready mode was disabled and it waits that all players are ready -> end warmup
  6522. -                               if(!g_Config.m_SvPlayerReadyMode && m_GameStateTimer == TIMER_INFINITE)
  6523. -                                       SetGameState(IGS_WARMUP_USER, 0);
  6524. -                               break;
  6525. -                       case IGS_START_COUNTDOWN:
  6526. -                       case IGS_GAME_PAUSED:
  6527. -                               // freeze the game
  6528. -                               ++m_GameStartTick;
  6529. -                               break;
  6530. -                       case IGS_WARMUP_GAME:
  6531. -                       case IGS_GAME_RUNNING:
  6532. -                       case IGS_END_MATCH:
  6533. -                       case IGS_END_ROUND:
  6534. -                               // not effected
  6535. -                               break;
  6536. -                       }
  6537. -               }
  6538. -       }
  6539. -
  6540. -       // do team-balancing (skip this in survival, done there when a round starts)
  6541. -       if(IsTeamplay() && !(m_GameFlags&GAMEFLAG_SURVIVAL))
  6542. -       {
  6543. -               switch(m_UnbalancedTick)
  6544. -               {
  6545. -               case TBALANCE_CHECK:
  6546. -                       CheckTeamBalance();
  6547. -                       break;
  6548. -               case TBALANCE_OK:
  6549. -                       break;
  6550. -               default:
  6551. -                       if(Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
  6552. -                               DoTeamBalance();
  6553. -               }
  6554. -       }
  6555. -
  6556. -       // check for inactive players
  6557. -       DoActivityCheck();
  6558. -
  6559. -       // win check
  6560. -       if(m_GameState == IGS_GAME_RUNNING && !GameServer()->m_World.m_ResetRequested)
  6561. -       {
  6562. -               if(m_GameFlags&GAMEFLAG_SURVIVAL)
  6563. -                       DoWincheckRound();
  6564. -               else
  6565. -                       DoWincheckMatch();
  6566. -       }
  6567. -}
  6568. -
  6569. -// info
  6570. -bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) const
  6571. -{
  6572. -       if(ClientID1 == ClientID2)
  6573. -               return false;
  6574. -
  6575. -       if(IsTeamplay())
  6576. -       {
  6577. -               if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2])
  6578. -                       return false;
  6579. -
  6580. -               if(!g_Config.m_SvTeamdamage && GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam())
  6581. -                       return true;
  6582. -       }
  6583. -
  6584. -       return false;
  6585. -}
  6586. -
  6587. -bool IGameController::IsPlayerReadyMode() const
  6588. -{
  6589. -       return g_Config.m_SvPlayerReadyMode != 0 && (m_GameStateTimer == TIMER_INFINITE && (m_GameState == IGS_WARMUP_USER || m_GameState == IGS_GAME_PAUSED));
  6590. +       GameServer()->m_World.m_Paused = true;
  6591. +       m_GameOverTick = Server()->Tick();
  6592. +       m_SuddenDeath = 0;
  6593.  }
  6594.  
  6595. -bool IGameController::IsTeamChangeAllowed() const
  6596. +void IGameController::ResetGame()
  6597.  {
  6598. -       return !GameServer()->m_World.m_Paused || (m_GameState == IGS_START_COUNTDOWN && m_GameStartTick == Server()->Tick());
  6599. +       GameServer()->m_World.m_ResetRequested = true;
  6600.  }
  6601.  
  6602. -const char *IGameController::GetTeamName(int Team) const
  6603. +const char *IGameController::GetTeamName(int Team)
  6604.  {
  6605.         if(IsTeamplay())
  6606.         {
  6607. @@ -808,19 +195,38 @@
  6608.                 else if(Team == TEAM_BLUE)
  6609.                         return "blue team";
  6610.         }
  6611. -       else if(Team == 0)
  6612. -               return "game";
  6613. +       else
  6614. +       {
  6615. +               if(Team == 0)
  6616. +                       return "game";
  6617. +       }
  6618.  
  6619.         return "spectators";
  6620.  }
  6621.  
  6622. -// map
  6623.  static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
  6624.  
  6625. +void IGameController::StartRound()
  6626. +{
  6627. +       ResetGame();
  6628. +
  6629. +       m_RoundStartTick = Server()->Tick();
  6630. +       m_SuddenDeath = 0;
  6631. +       m_GameOverTick = -1;
  6632. +       GameServer()->m_World.m_Paused = false;
  6633. +       m_aTeamscore[TEAM_RED] = 0;
  6634. +       m_aTeamscore[TEAM_BLUE] = 0;
  6635. +       m_ForceBalanced = false;
  6636. +       Server()->DemoRecorder_HandleAutoStart();
  6637. +       char aBuf[256];
  6638. +       str_format(aBuf, sizeof(aBuf), "start round type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS);
  6639. +       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  6640. +}
  6641. +
  6642.  void IGameController::ChangeMap(const char *pToMap)
  6643.  {
  6644.         str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish));
  6645. -       EndMatch();
  6646. +       EndRound();
  6647.  }
  6648.  
  6649.  void IGameController::CycleMap()
  6650. @@ -832,15 +238,15 @@
  6651.                 GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  6652.                 str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap));
  6653.                 m_aMapWish[0] = 0;
  6654. -               m_MatchCount = 0;
  6655. +               m_RoundCount = 0;
  6656.                 return;
  6657.         }
  6658.         if(!str_length(g_Config.m_SvMaprotation))
  6659.                 return;
  6660.  
  6661. -       if(m_MatchCount < g_Config.m_SvMatchesPerMap-1)
  6662. +       if(m_RoundCount < g_Config.m_SvRoundsPerMap-1)
  6663.         {
  6664. -               if(g_Config.m_SvMatchSwap)
  6665. +               if(g_Config.m_SvRoundSwap)
  6666.                         GameServer()->SwapTeams();
  6667.                 return;
  6668.         }
  6669. @@ -891,7 +297,7 @@
  6670.         while(IsSeparator(aBuf[i]))
  6671.                 i++;
  6672.  
  6673. -       m_MatchCount = 0;
  6674. +       m_RoundCount = 0;
  6675.  
  6676.         char aBufMsg[256];
  6677.         str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]);
  6678. @@ -899,202 +305,431 @@
  6679.         str_copy(g_Config.m_SvMap, &aBuf[i], sizeof(g_Config.m_SvMap));
  6680.  }
  6681.  
  6682. -// spawn
  6683. -bool IGameController::CanSpawn(int Team, vec2 *pOutPos) const
  6684. +void IGameController::PostReset()
  6685.  {
  6686. -       // spectators can't spawn
  6687. -       if(Team == TEAM_SPECTATORS || GameServer()->m_World.m_Paused || GameServer()->m_World.m_ResetRequested)
  6688. -               return false;
  6689. -
  6690. -       CSpawnEval Eval;
  6691. +       for(int i = 0; i < MAX_CLIENTS; i++)
  6692. +       {
  6693. +               if(GameServer()->m_apPlayers[i])
  6694. +               {
  6695. +                       GameServer()->m_apPlayers[i]->Respawn();
  6696. +                       GameServer()->m_apPlayers[i]->m_Score = 0;
  6697. +                       GameServer()->m_apPlayers[i]->m_ScoreStartTick = Server()->Tick();
  6698. +                       GameServer()->m_apPlayers[i]->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  6699. +               }
  6700. +       }
  6701. +}
  6702.  
  6703. +void IGameController::OnPlayerInfoChange(class CPlayer *pP)
  6704. +{
  6705. +       const int aTeamColors[2] = {65387, 10223467};
  6706.         if(IsTeamplay())
  6707.         {
  6708. -               Eval.m_FriendlyTeam = Team;
  6709. -
  6710. -               // first try own team spawn, then normal spawn and then enemy
  6711. -               EvaluateSpawnType(&Eval, 1+(Team&1));
  6712. -               if(!Eval.m_Got)
  6713. +               pP->m_TeeInfos.m_UseCustomColor = 1;
  6714. +               if(pP->GetTeam() >= TEAM_RED && pP->GetTeam() <= TEAM_BLUE)
  6715.                 {
  6716. -                       EvaluateSpawnType(&Eval, 0);
  6717. -                       if(!Eval.m_Got)
  6718. -                               EvaluateSpawnType(&Eval, 1+((Team+1)&1));
  6719. +                       pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()];
  6720. +                       pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()];
  6721. +               }
  6722. +               else
  6723. +               {
  6724. +                       pP->m_TeeInfos.m_ColorBody = 12895054;
  6725. +                       pP->m_TeeInfos.m_ColorFeet = 12895054;
  6726.                 }
  6727.         }
  6728. +}
  6729. +
  6730. +
  6731. +int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
  6732. +{
  6733. +       // do scoreing
  6734. +       if(!pKiller || Weapon == WEAPON_GAME)
  6735. +               return 0;
  6736. +       if(pKiller != pVictim->GetPlayer() && pVictim->frz_tick > 0)
  6737. +               pVictim->GetPlayer()->m_Score--; // suicide while frozen causes -1 score
  6738.         else
  6739.         {
  6740. -               EvaluateSpawnType(&Eval, 0);
  6741. -               EvaluateSpawnType(&Eval, 1);
  6742. -               EvaluateSpawnType(&Eval, 2);
  6743. +               if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam())
  6744. +                       return 0; // teamkill
  6745. +               else
  6746. +                       return 0;
  6747.         }
  6748. +       if(Weapon == WEAPON_SELF)
  6749. +               pVictim->GetPlayer()->m_RespawnTick = 0.5;
  6750. +       return 0;
  6751. +}
  6752.  
  6753. -       *pOutPos = Eval.m_Pos;
  6754. -       return Eval.m_Got;
  6755. +void IGameController::OnCharacterSpawn(class CCharacter *pChr)
  6756. +{
  6757. +       // default health
  6758. +       pChr->IncreaseHealth(10);
  6759. +
  6760. +       // give default weapons
  6761. +       //hammer second
  6762. +       pChr->GiveWeapon(WEAPON_GUN, 10);
  6763. +       pChr->GiveWeapon(WEAPON_HAMMER, -1);
  6764.  }
  6765.  
  6766. -float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) const
  6767. +void IGameController::DoWarmup(int Seconds)
  6768.  {
  6769. -       float Score = 0.0f;
  6770. -       CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER));
  6771. -       for(; pC; pC = (CCharacter *)pC->TypeNext())
  6772. +       if(Seconds < 0)
  6773. +               m_Warmup = 0;
  6774. +       else
  6775. +               m_Warmup = Seconds*Server()->TickSpeed();
  6776. +}
  6777. +
  6778. +bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2)
  6779. +{
  6780. +       if(ClientID1 == ClientID2)
  6781. +               return false;
  6782. +
  6783. +       if(IsTeamplay())
  6784.         {
  6785. -               // team mates are not as dangerous as enemies
  6786. -               float Scoremod = 1.0f;
  6787. -               if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam)
  6788. -                       Scoremod = 0.5f;
  6789. +               if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2])
  6790. +                       return false;
  6791.  
  6792. -               float d = distance(Pos, pC->m_Pos);
  6793. -               Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d);
  6794. +               if(GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam())
  6795. +                       return true;
  6796.         }
  6797.  
  6798. -       return Score;
  6799. +       return false;
  6800.  }
  6801.  
  6802. -void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type) const
  6803. +bool IGameController::IsForceBalanced()
  6804.  {
  6805. -       // get spawn point
  6806. -       for(int i = 0; i < m_aNumSpawnPoints[Type]; i++)
  6807. +       if(m_ForceBalanced)
  6808.         {
  6809. -               // check if the position is occupado
  6810. -               CCharacter *aEnts[MAX_CLIENTS];
  6811. -               int Num = GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
  6812. -               vec2 Positions[5] = { vec2(0.0f, 0.0f), vec2(-32.0f, 0.0f), vec2(0.0f, -32.0f), vec2(32.0f, 0.0f), vec2(0.0f, 32.0f) }; // start, left, up, right, down
  6813. -               int Result = -1;
  6814. -               for(int Index = 0; Index < 5 && Result == -1; ++Index)
  6815. +               m_ForceBalanced = false;
  6816. +               return true;
  6817. +       }
  6818. +       else
  6819. +               return false;
  6820. +}
  6821. +
  6822. +bool IGameController::CanBeMovedOnBalance(int ClientID)
  6823. +{
  6824. +       return true;
  6825. +}
  6826. +
  6827. +void IGameController::Tick()
  6828. +{
  6829. +       // do warmup
  6830. +       if(m_Warmup)
  6831. +       {
  6832. +               m_Warmup--;
  6833. +               if(!m_Warmup)
  6834. +                       StartRound();
  6835. +       }
  6836. +
  6837. +       if(m_GameOverTick != -1)
  6838. +       {
  6839. +               // game over.. wait for restart
  6840. +               if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10)
  6841.                 {
  6842. -                       Result = Index;
  6843. -                       for(int c = 0; c < Num; ++c)
  6844. -                               if(GameServer()->Collision()->CheckPoint(m_aaSpawnPoints[Type][i]+Positions[Index]) ||
  6845. -                                       distance(aEnts[c]->m_Pos, m_aaSpawnPoints[Type][i]+Positions[Index]) <= aEnts[c]->m_ProximityRadius)
  6846. +                       CycleMap();
  6847. +                       StartRound();
  6848. +                       m_RoundCount++;
  6849. +               }
  6850. +       }
  6851. +
  6852. +       // game is Paused
  6853. +       if(GameServer()->m_World.m_Paused)
  6854. +               ++m_RoundStartTick;
  6855. +
  6856. +       // do team-balancing
  6857. +       if(IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
  6858. +       {
  6859. +               GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams");
  6860. +
  6861. +               int aT[2] = {0,0};
  6862. +               float aTScore[2] = {0,0};
  6863. +               float aPScore[MAX_CLIENTS] = {0.0f};
  6864. +               for(int i = 0; i < MAX_CLIENTS; i++)
  6865. +               {
  6866. +                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  6867. +                       {
  6868. +                               aT[GameServer()->m_apPlayers[i]->GetTeam()]++;
  6869. +                               aPScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/
  6870. +                                       (Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick);
  6871. +                               aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPScore[i];
  6872. +                       }
  6873. +               }
  6874. +
  6875. +               // are teams unbalanced?
  6876. +               if(absolute(aT[0]-aT[1]) >= 2)
  6877. +               {
  6878. +                       int M = (aT[0] > aT[1]) ? 0 : 1;
  6879. +                       int NumBalance = absolute(aT[0]-aT[1]) / 2;
  6880. +
  6881. +                       do
  6882. +                       {
  6883. +                               CPlayer *pP = 0;
  6884. +                               float PD = aTScore[M];
  6885. +                               for(int i = 0; i < MAX_CLIENTS; i++)
  6886.                                 {
  6887. -                                       Result = -1;
  6888. -                                       break;
  6889. +                                       if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i))
  6890. +                                               continue;
  6891. +                                       // remember the player who would cause lowest score-difference
  6892. +                                       if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])) < PD))
  6893. +                                       {
  6894. +                                               pP = GameServer()->m_apPlayers[i];
  6895. +                                               PD = absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i]));
  6896. +                                       }
  6897.                                 }
  6898. +
  6899. +                               // move the player to the other team
  6900. +                               int Temp = pP->m_LastActionTick;
  6901. +                               pP->SetTeam(M^1);
  6902. +                               pP->m_LastActionTick = Temp;
  6903. +
  6904. +                               pP->Respawn();
  6905. +                               pP->m_ForceBalanced = true;
  6906. +                       } while (--NumBalance);
  6907. +
  6908. +                       m_ForceBalanced = true;
  6909.                 }
  6910. -               if(Result == -1)
  6911. -                       continue;       // try next spawn point
  6912. +               m_UnbalancedTick = -1;
  6913. +       }
  6914.  
  6915. -               vec2 P = m_aaSpawnPoints[Type][i]+Positions[Result];
  6916. -               float S = EvaluateSpawnPos(pEval, P);
  6917. -               if(!pEval->m_Got || pEval->m_Score > S)
  6918. +       // check for inactive players
  6919. +       if(g_Config.m_SvInactiveKickTime > 0)
  6920. +       {
  6921. +               for(int i = 0; i < MAX_CLIENTS; ++i)
  6922.                 {
  6923. -                       pEval->m_Got = true;
  6924. -                       pEval->m_Score = S;
  6925. -                       pEval->m_Pos = P;
  6926. +               #ifdef CONF_DEBUG
  6927. +                       if(g_Config.m_DbgDummies)
  6928. +                       {
  6929. +                               if(i >= MAX_CLIENTS-g_Config.m_DbgDummies)
  6930. +                                       break;
  6931. +                       }
  6932. +               #endif
  6933. +                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && !Server()->IsAuthed(i))
  6934. +                       {
  6935. +                               if(Server()->Tick() > GameServer()->m_apPlayers[i]->m_LastActionTick+g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60)
  6936. +                               {
  6937. +                                       switch(g_Config.m_SvInactiveKick)
  6938. +                                       {
  6939. +                                       case 0:
  6940. +                                               {
  6941. +                                                       // move player to spectator
  6942. +                                                       GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS);
  6943. +                                               }
  6944. +                                               break;
  6945. +                                       case 1:
  6946. +                                               {
  6947. +                                                       // move player to spectator if the reserved slots aren't filled yet, kick him otherwise
  6948. +                                                       int Spectators = 0;
  6949. +                                                       for(int j = 0; j < MAX_CLIENTS; ++j)
  6950. +                                                               if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS)
  6951. +                                                                       ++Spectators;
  6952. +                                                       if(Spectators >= g_Config.m_SvSpectatorSlots)
  6953. +                                                               Server()->Kick(i, "Kicked for inactivity");
  6954. +                                                       else
  6955. +                                                               GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS);
  6956. +                                               }
  6957. +                                               break;
  6958. +                                       case 2:
  6959. +                                               {
  6960. +                                                       // kick the player
  6961. +                                                       Server()->Kick(i, "Kicked for inactivity");
  6962. +                                               }
  6963. +                                       }
  6964. +                               }
  6965. +                       }
  6966.                 }
  6967.         }
  6968. +
  6969. +       DoWincheck();
  6970.  }
  6971.  
  6972. -bool IGameController::GetStartRespawnState() const
  6973. +
  6974. +bool IGameController::IsTeamplay() const
  6975.  {
  6976. -       if(m_GameFlags&GAMEFLAG_SURVIVAL)
  6977. -       {
  6978. -               // players can always respawn during warmup or match/round start countdown
  6979. -               if(m_GameState == IGS_WARMUP_GAME || m_GameState == IGS_WARMUP_USER || (m_GameState == IGS_START_COUNTDOWN && m_GameStartTick == Server()->Tick()))
  6980. -                       return false;
  6981. -               else
  6982. -                       return true;
  6983. -       }
  6984. -       else
  6985. -               return false;
  6986. +       return m_GameFlags&GAMEFLAG_TEAMS;
  6987.  }
  6988.  
  6989. -// team
  6990. -bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) const
  6991. +void IGameController::Snap(int SnappingClient)
  6992.  {
  6993. -       if(!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime)
  6994. -               return true;
  6995. +       CNetObj_GameInfo *pGameInfoObj = (CNetObj_GameInfo *)Server()->SnapNewItem(NETOBJTYPE_GAMEINFO, 0, sizeof(CNetObj_GameInfo));
  6996. +       if(!pGameInfoObj)
  6997. +               return;
  6998. +
  6999. +       pGameInfoObj->m_GameFlags = m_GameFlags;
  7000. +       pGameInfoObj->m_GameStateFlags = 0;
  7001. +       if(m_GameOverTick != -1)
  7002. +               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_GAMEOVER;
  7003. +       if(m_SuddenDeath)
  7004. +               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_SUDDENDEATH;
  7005. +       if(GameServer()->m_World.m_Paused)
  7006. +               pGameInfoObj->m_GameStateFlags |= GAMESTATEFLAG_PAUSED;
  7007. +       pGameInfoObj->m_RoundStartTick = m_RoundStartTick;
  7008. +       pGameInfoObj->m_WarmupTimer = m_Warmup;
  7009. +
  7010. +       pGameInfoObj->m_ScoreLimit = g_Config.m_SvScorelimit;
  7011. +       pGameInfoObj->m_TimeLimit = g_Config.m_SvTimelimit;
  7012. +
  7013. +       pGameInfoObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0;
  7014. +       pGameInfoObj->m_RoundCurrent = m_RoundCount+1;
  7015. +}
  7016. +
  7017. +int IGameController::GetAutoTeam(int NotThisID)
  7018. +{
  7019. +       // this will force the auto balancer to work overtime aswell
  7020. +       if(g_Config.m_DbgStress)
  7021. +               return 0;
  7022.  
  7023. -       // simulate what would happen if the player changes team
  7024. -       int aPlayerCount[NUM_TEAMS] = { m_aTeamSize[TEAM_RED], m_aTeamSize[TEAM_BLUE] };
  7025. -       aPlayerCount[JoinTeam]++;
  7026. -       if(pPlayer->GetTeam() != TEAM_SPECTATORS)
  7027. -               aPlayerCount[JoinTeam^1]--;
  7028. +       int aNumplayers[2] = {0,0};
  7029. +       for(int i = 0; i < MAX_CLIENTS; i++)
  7030. +       {
  7031. +               if(GameServer()->m_apPlayers[i] && i != NotThisID)
  7032. +               {
  7033. +                       if(GameServer()->m_apPlayers[i]->GetTeam() >= TEAM_RED && GameServer()->m_apPlayers[i]->GetTeam() <= TEAM_BLUE)
  7034. +                               aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
  7035. +               }
  7036. +       }
  7037. +
  7038. +       int Team = 0;
  7039. +       if(IsTeamplay())
  7040. +               Team = aNumplayers[TEAM_RED] > aNumplayers[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED;
  7041.  
  7042. -       // check if the player-difference decreases or is smaller than 2
  7043. -       return aPlayerCount[JoinTeam]-aPlayerCount[JoinTeam^1] < NUM_TEAMS;
  7044. +       if(CanJoinTeam(Team, NotThisID))
  7045. +               return Team;
  7046. +       return -1;
  7047.  }
  7048.  
  7049. -bool IGameController::CanJoinTeam(int Team, int NotThisID) const
  7050. +bool IGameController::CanJoinTeam(int Team, int NotThisID)
  7051.  {
  7052.         if(Team == TEAM_SPECTATORS || (GameServer()->m_apPlayers[NotThisID] && GameServer()->m_apPlayers[NotThisID]->GetTeam() != TEAM_SPECTATORS))
  7053.                 return true;
  7054.  
  7055. -       // check if there're enough player slots left
  7056. -       return m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < Server()->MaxClients()-g_Config.m_SvSpectatorSlots;
  7057. +       int aNumplayers[2] = {0,0};
  7058. +       for(int i = 0; i < MAX_CLIENTS; i++)
  7059. +       {
  7060. +               if(GameServer()->m_apPlayers[i] && i != NotThisID)
  7061. +               {
  7062. +                       if(GameServer()->m_apPlayers[i]->GetTeam() >= TEAM_RED && GameServer()->m_apPlayers[i]->GetTeam() <= TEAM_BLUE)
  7063. +                               aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
  7064. +               }
  7065. +       }
  7066. +
  7067. +       return (aNumplayers[0] + aNumplayers[1]) < Server()->MaxClients()-g_Config.m_SvSpectatorSlots;
  7068.  }
  7069.  
  7070. -int IGameController::ClampTeam(int Team) const
  7071. +bool IGameController::CheckTeamBalance()
  7072.  {
  7073. -       if(Team < TEAM_RED)
  7074. -               return TEAM_SPECTATORS;
  7075. -       if(IsTeamplay())
  7076. -               return Team&1;
  7077. -       return TEAM_RED;
  7078. +       if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime)
  7079. +               return true;
  7080. +
  7081. +       int aT[2] = {0, 0};
  7082. +       for(int i = 0; i < MAX_CLIENTS; i++)
  7083. +       {
  7084. +               CPlayer *pP = GameServer()->m_apPlayers[i];
  7085. +               if(pP && pP->GetTeam() != TEAM_SPECTATORS)
  7086. +                       aT[pP->GetTeam()]++;
  7087. +       }
  7088. +
  7089. +       char aBuf[256];
  7090. +       if(absolute(aT[0]-aT[1]) >= 2)
  7091. +       {
  7092. +               str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", aT[0], aT[1]);
  7093. +               GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  7094. +               if(GameServer()->m_pController->m_UnbalancedTick == -1)
  7095. +                       GameServer()->m_pController->m_UnbalancedTick = Server()->Tick();
  7096. +               return false;
  7097. +       }
  7098. +       else
  7099. +       {
  7100. +               str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", aT[0], aT[1]);
  7101. +               GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  7102. +               GameServer()->m_pController->m_UnbalancedTick = -1;
  7103. +               return true;
  7104. +       }
  7105.  }
  7106.  
  7107. -void IGameController::DoTeamChange(CPlayer *pPlayer, int Team, bool DoChatMsg)
  7108. +bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam)
  7109.  {
  7110. -       Team = ClampTeam(Team);
  7111. -       if(Team == pPlayer->GetTeam())
  7112. -               return;
  7113. +       int aT[2] = {0, 0};
  7114.  
  7115. -       int OldTeam = pPlayer->GetTeam();
  7116. -       pPlayer->SetTeam(Team);
  7117. +       if (!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime)
  7118. +               return true;
  7119.  
  7120. -       int ClientID = pPlayer->GetCID();
  7121. -       char aBuf[128];
  7122. -       if(DoChatMsg)
  7123. +       for(int i = 0; i < MAX_CLIENTS; i++)
  7124.         {
  7125. -               str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(ClientID), GetTeamName(Team));
  7126. -               GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  7127. +               CPlayer *pP = GameServer()->m_apPlayers[i];
  7128. +               if(pP && pP->GetTeam() != TEAM_SPECTATORS)
  7129. +                       aT[pP->GetTeam()]++;
  7130.         }
  7131.  
  7132. -       str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", ClientID, Server()->ClientName(ClientID), Team);
  7133. -       GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  7134. +       // simulate what would happen if changed team
  7135. +       aT[JoinTeam]++;
  7136. +       if (pPlayer->GetTeam() != TEAM_SPECTATORS)
  7137. +               aT[JoinTeam^1]--;
  7138.  
  7139. -       // update effected game settings
  7140. -       if(OldTeam != TEAM_SPECTATORS)
  7141. +       // there is a player-difference of at least 2
  7142. +       if(absolute(aT[0]-aT[1]) >= 2)
  7143.         {
  7144. -               --m_aTeamSize[OldTeam];
  7145. -               m_UnbalancedTick = TBALANCE_CHECK;
  7146. +               // player wants to join team with less players
  7147. +               if ((aT[0] < aT[1] && JoinTeam == TEAM_RED) || (aT[0] > aT[1] && JoinTeam == TEAM_BLUE))
  7148. +                       return true;
  7149. +               else
  7150. +                       return false;
  7151.         }
  7152. -       if(Team != TEAM_SPECTATORS)
  7153. +       else
  7154. +               return true;
  7155. +}
  7156. +
  7157. +void IGameController::DoWincheck()
  7158. +{
  7159. +       if(m_GameOverTick == -1 && !m_Warmup && !GameServer()->m_World.m_ResetRequested)
  7160.         {
  7161. -               ++m_aTeamSize[Team];
  7162. -               m_UnbalancedTick = TBALANCE_CHECK;
  7163. -               if(m_GameState == IGS_WARMUP_GAME && HasEnoughPlayers())
  7164. -                       SetGameState(IGS_WARMUP_GAME, 0);
  7165. -               pPlayer->m_IsReadyToPlay = !IsPlayerReadyMode();
  7166. -               if(m_GameFlags&GAMEFLAG_SURVIVAL)
  7167. -                       pPlayer->m_RespawnDisabled = GetStartRespawnState();
  7168. +               if(IsTeamplay())
  7169. +               {
  7170. +                       // check score win condition
  7171. +                       if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
  7172. +                               (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  7173. +                       {
  7174. +                               if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
  7175. +                                       EndRound();
  7176. +                               else
  7177. +                                       m_SuddenDeath = 1;
  7178. +                       }
  7179. +               }
  7180. +               else
  7181. +               {
  7182. +                       // gather some stats
  7183. +                       int Topscore = 0;
  7184. +                       int TopscoreCount = 0;
  7185. +                       for(int i = 0; i < MAX_CLIENTS; i++)
  7186. +                       {
  7187. +                               if(GameServer()->m_apPlayers[i])
  7188. +                               {
  7189. +                                       if(GameServer()->m_apPlayers[i]->m_Score > Topscore)
  7190. +                                       {
  7191. +                                               Topscore = GameServer()->m_apPlayers[i]->m_Score;
  7192. +                                               TopscoreCount = 1;
  7193. +                                       }
  7194. +                                       else if(GameServer()->m_apPlayers[i]->m_Score == Topscore)
  7195. +                                               TopscoreCount++;
  7196. +                               }
  7197. +                       }
  7198. +
  7199. +                       // check score win condition
  7200. +                       if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) ||
  7201. +                               (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  7202. +                       {
  7203. +                               if(TopscoreCount == 1)
  7204. +                                       EndRound();
  7205. +                               else
  7206. +                                       m_SuddenDeath = 1;
  7207. +                       }
  7208. +               }
  7209.         }
  7210. -       OnPlayerInfoChange(pPlayer);
  7211. -       GameServer()->OnClientTeamChange(ClientID);
  7212.  }
  7213.  
  7214. -int IGameController::GetStartTeam()
  7215. +int IGameController::ClampTeam(int Team)
  7216.  {
  7217. -       // this will force the auto balancer to work overtime aswell
  7218. -       if(g_Config.m_DbgStress)
  7219. -               return TEAM_RED;
  7220. -
  7221. -       if(g_Config.m_SvTournamentMode)
  7222. +       if(Team < 0)
  7223.                 return TEAM_SPECTATORS;
  7224. -
  7225. -       // determine new team
  7226. -       int Team = TEAM_RED;
  7227.         if(IsTeamplay())
  7228. -               Team = m_aTeamSize[TEAM_RED] > m_aTeamSize[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED;
  7229. -
  7230. -       // check if there're enough player slots left
  7231. -       if(m_aTeamSize[TEAM_RED]+m_aTeamSize[TEAM_BLUE] < Server()->MaxClients()-g_Config.m_SvSpectatorSlots)
  7232. -       {
  7233. -               ++m_aTeamSize[Team];
  7234. -               m_UnbalancedTick = TBALANCE_CHECK;
  7235. -               if(m_GameState == IGS_WARMUP_GAME && HasEnoughPlayers())
  7236. -                       SetGameState(IGS_WARMUP_GAME, 0);
  7237. -               return Team;
  7238. -       }
  7239. -       return TEAM_SPECTATORS;
  7240. +               return Team&1;
  7241. +       return 0;
  7242.  }
  7243. diff -Naur ../teeworlds/src/game/server/gamecontroller.h src/game/server/gamecontroller.h
  7244. --- ../teeworlds/src/game/server/gamecontroller.h       2012-06-26 16:53:53.396862075 +1000
  7245. +++ src/game/server/gamecontroller.h    2012-07-08 19:42:32.842259599 +1000
  7246. @@ -5,7 +5,14 @@
  7247.  
  7248.  #include <base/vmath.h>
  7249.  
  7250. -#include <game/generated/protocol.h>
  7251. +#ifdef _MSC_VER
  7252. +typedef __int32 int32_t;
  7253. +typedef unsigned __int32 uint32_t;
  7254. +typedef __int64 int64_t;
  7255. +typedef unsigned __int64 uint64_t;
  7256. +#else
  7257. +#include <stdint.h>
  7258. +#endif
  7259.  
  7260.  /*
  7261.         Class: Game Controller
  7262. @@ -14,59 +21,16 @@
  7263.  */
  7264.  class IGameController
  7265.  {
  7266. +       vec2 m_aaSpawnPoints[3][64];
  7267. +       int m_aNumSpawnPoints[3];
  7268. +
  7269.         class CGameContext *m_pGameServer;
  7270.         class IServer *m_pServer;
  7271.  
  7272. -       // activity
  7273. -       void DoActivityCheck();
  7274. -       bool GetPlayersReadyState();
  7275. -       void SetPlayersReadyState(bool ReadyState);
  7276. -
  7277. -       // balancing
  7278. -       enum
  7279. -       {
  7280. -               TBALANCE_CHECK=-2,
  7281. -               TBALANCE_OK,
  7282. -       };
  7283. -       int m_aTeamSize[NUM_TEAMS];
  7284. -       int m_UnbalancedTick;
  7285. -
  7286. -       virtual bool CanBeMovedOnBalance(int ClientID) const;
  7287. -       void CheckTeamBalance();
  7288. -       void DoTeamBalance();
  7289. -
  7290. -       // game
  7291. -       enum EGameState
  7292. -       {
  7293. -               // internal game states
  7294. -               IGS_WARMUP_GAME,                // warmup started by game because there're not enough players (infinite)
  7295. -               IGS_WARMUP_USER,                // warmup started by user action via rcon or new match (infinite or timer)
  7296. -
  7297. -               IGS_START_COUNTDOWN,    // start countown to unpause the game or start match/round (tick timer)
  7298. -
  7299. -               IGS_GAME_PAUSED,                // game paused (infinite or tick timer)
  7300. -               IGS_GAME_RUNNING,               // game running (infinite)
  7301. -              
  7302. -               IGS_END_MATCH,                  // match is over (tick timer)
  7303. -               IGS_END_ROUND,                  // round is over (tick timer)
  7304. -       };
  7305. -       EGameState m_GameState;
  7306. -       int m_GameStateTimer;
  7307. -
  7308. -       virtual void DoWincheckMatch();
  7309. -       virtual void DoWincheckRound() {};
  7310. -       bool HasEnoughPlayers() const { return (IsTeamplay() && m_aTeamSize[TEAM_RED] > 0 && m_aTeamSize[TEAM_BLUE] > 0) || (!IsTeamplay() && m_aTeamSize[TEAM_RED] > 1); }
  7311. -       void ResetGame();
  7312. -       void SetGameState(EGameState GameState, int Timer=0);
  7313. -       void StartMatch();
  7314. -       void StartRound();
  7315. -
  7316. -       // map
  7317. -       char m_aMapWish[128];
  7318. -      
  7319. -       void CycleMap();
  7320. +protected:
  7321. +       CGameContext *GameServer() const { return m_pGameServer; }
  7322. +       IServer *Server() const { return m_pServer; }
  7323.  
  7324. -       // spawn
  7325.         struct CSpawnEval
  7326.         {
  7327.                 CSpawnEval()
  7328. @@ -81,57 +45,59 @@
  7329.                 int m_FriendlyTeam;
  7330.                 float m_Score;
  7331.         };
  7332. -       vec2 m_aaSpawnPoints[3][64];
  7333. -       int m_aNumSpawnPoints[3];
  7334. -      
  7335. -       float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) const;
  7336. -       void EvaluateSpawnType(CSpawnEval *pEval, int Type) const;
  7337.  
  7338. -       // team
  7339. -       int ClampTeam(int Team) const;
  7340. +       float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos);
  7341. +       void EvaluateSpawnType(CSpawnEval *pEval, int Type);
  7342. +       bool EvaluateSpawn(class CPlayer *pP, vec2 *pPos);
  7343.  
  7344. -protected:
  7345. -       CGameContext *GameServer() const { return m_pGameServer; }
  7346. -       IServer *Server() const { return m_pServer; }
  7347. +       void CycleMap();
  7348. +       void ResetGame();
  7349.  
  7350. -       // game
  7351. -       int m_GameStartTick;
  7352. -       int m_MatchCount;
  7353. -       int m_RoundCount;
  7354. +       char m_aMapWish[128];
  7355. +
  7356. +
  7357. +       int m_RoundStartTick;
  7358. +       int m_GameOverTick;
  7359.         int m_SuddenDeath;
  7360. -       int m_aTeamscore[NUM_TEAMS];
  7361.  
  7362. -       void EndMatch() { SetGameState(IGS_END_MATCH, 10); }
  7363. -       void EndRound() { SetGameState(IGS_END_ROUND, 10); }
  7364. +       int m_aTeamscore[2];
  7365. +
  7366. +       int m_Warmup;
  7367. +       int m_RoundCount;
  7368.  
  7369. -       // info
  7370.         int m_GameFlags;
  7371. -       const char *m_pGameType;
  7372. +       int m_UnbalancedTick;
  7373. +       bool m_ForceBalanced;
  7374.  
  7375.  public:
  7376. +       const char *m_pGameType;
  7377. +
  7378. +       bool IsTeamplay() const;
  7379. +       bool IsGameOver() const { return m_GameOverTick != -1; }
  7380. +
  7381.         IGameController(class CGameContext *pGameServer);
  7382. -       virtual ~IGameController() {};
  7383. +       virtual ~IGameController();
  7384.  
  7385. -       // event
  7386. -       /*
  7387. -               Function: on_CCharacter_death
  7388. -                       Called when a CCharacter in the world dies.
  7389. +       virtual void DoWincheck();
  7390. +
  7391. +       void DoWarmup(int Seconds);
  7392. +
  7393. +       void StartRound();
  7394. +       void EndRound();
  7395. +       void ChangeMap(const char *pToMap);
  7396. +
  7397. +       bool IsFriendlyFire(int ClientID1, int ClientID2);
  7398. +
  7399. +       bool IsForceBalanced();
  7400.  
  7401. -               Arguments:
  7402. -                       victim - The CCharacter that died.
  7403. -                       killer - The player that killed it.
  7404. -                       weapon - What weapon that killed it. Can be -1 for undefined
  7405. -                               weapon when switching team or player suicides.
  7406. -       */
  7407. -       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7408.         /*
  7409. -               Function: on_CCharacter_spawn
  7410. -                       Called when a CCharacter spawns into the game world.
  7411.  
  7412. -               Arguments:
  7413. -                       chr - The CCharacter that was spawned.
  7414.         */
  7415. -       virtual void OnCharacterSpawn(class CCharacter *pChr);
  7416. +       virtual bool CanBeMovedOnBalance(int ClientID);
  7417. +
  7418. +       virtual void Tick();
  7419. +
  7420. +       virtual void Snap(int SnappingClient);
  7421.  
  7422.         /*
  7423.                 Function: on_entity
  7424. @@ -147,49 +113,44 @@
  7425.         */
  7426.         virtual bool OnEntity(int Index, vec2 Pos);
  7427.  
  7428. -       void OnPlayerDisconnect(class CPlayer *pPlayer, const char *pReason);
  7429. -       void OnPlayerInfoChange(class CPlayer *pPlayer);
  7430. -       void OnPlayerReadyChange(class CPlayer *pPlayer);
  7431. +       /*
  7432. +               Function: on_CCharacter_spawn
  7433. +                       Called when a CCharacter spawns into the game world.
  7434. +
  7435. +               Arguments:
  7436. +                       chr - The CCharacter that was spawned.
  7437. +       */
  7438. +       virtual void OnCharacterSpawn(class CCharacter *pChr);
  7439. +
  7440. +       /*
  7441. +               Function: on_CCharacter_death
  7442. +                       Called when a CCharacter in the world dies.
  7443. +
  7444. +               Arguments:
  7445. +                       victim - The CCharacter that died.
  7446. +                       killer - The player that killed it.
  7447. +                       weapon - What weapon that killed it. Can be -1 for undefined
  7448. +                               weapon when switching team or player suicides.
  7449. +       */
  7450. +       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7451.  
  7452. -       void OnReset();
  7453.  
  7454. -       // game
  7455. -       enum
  7456. -       {
  7457. -               TIMER_INFINITE = -1,
  7458. -       };
  7459. +       virtual void OnPlayerInfoChange(class CPlayer *pP);
  7460.  
  7461. -       void DoPause(int Seconds) { SetGameState(IGS_GAME_PAUSED, Seconds); }
  7462. -       void DoWarmup(int Seconds) { SetGameState(IGS_WARMUP_USER, Seconds); }
  7463. +       //
  7464. +       virtual bool CanSpawn(int Team, vec2 *pPos);
  7465.  
  7466. -       // general
  7467. -       virtual void Snap(int SnappingClient);
  7468. -       virtual void Tick();
  7469. +       /*
  7470.  
  7471. -       // info
  7472. -       bool IsFriendlyFire(int ClientID1, int ClientID2) const;
  7473. -       bool IsGamePaused() const { return m_GameState == IGS_GAME_PAUSED || m_GameState == IGS_START_COUNTDOWN; }
  7474. -       bool IsPlayerReadyMode() const;
  7475. -       bool IsTeamChangeAllowed() const;
  7476. -       bool IsTeamplay() const { return m_GameFlags&GAMEFLAG_TEAMS; }
  7477. -      
  7478. -       const char *GetGameType() const { return m_pGameType; }
  7479. -       const char *GetTeamName(int Team) const;
  7480. -      
  7481. -       // map
  7482. -       void ChangeMap(const char *pToMap);
  7483. +       */
  7484. +       virtual const char *GetTeamName(int Team);
  7485. +       virtual int GetAutoTeam(int NotThisID);
  7486. +       virtual bool CanJoinTeam(int Team, int NotThisID);
  7487. +       bool CheckTeamBalance();
  7488. +       bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam);
  7489. +       int ClampTeam(int Team);
  7490.  
  7491. -       //spawn
  7492. -       bool CanSpawn(int Team, vec2 *pPos) const;
  7493. -       bool GetStartRespawnState() const;
  7494. -
  7495. -       // team
  7496. -       bool CanJoinTeam(int Team, int NotThisID) const;
  7497. -       bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam) const;
  7498. -
  7499. -       void DoTeamChange(class CPlayer *pPlayer, int Team, bool DoChatMsg=true);
  7500. -      
  7501. -       int GetStartTeam();
  7502. +       virtual void PostReset();
  7503.  };
  7504.  
  7505.  #endif
  7506. diff -Naur ../teeworlds/src/game/server/gamemodes/ctf.cpp src/game/server/gamemodes/ctf.cpp
  7507. --- ../teeworlds/src/game/server/gamemodes/ctf.cpp      2012-06-26 16:53:53.396862075 +1000
  7508. +++ src/game/server/gamemodes/ctf.cpp   2012-07-08 19:42:32.842259599 +1000
  7509. @@ -6,38 +6,39 @@
  7510.  
  7511.  #include <game/server/entities/character.h>
  7512.  #include <game/server/entities/flag.h>
  7513. -#include <game/server/gamecontext.h>
  7514.  #include <game/server/player.h>
  7515. +#include <game/server/gamecontext.h>
  7516.  #include "ctf.h"
  7517.  
  7518. -CGameControllerCTF::CGameControllerCTF(CGameContext *pGameServer)
  7519. +CGameControllerCTF::CGameControllerCTF(class CGameContext *pGameServer)
  7520.  : IGameController(pGameServer)
  7521.  {
  7522. -       // game
  7523.         m_apFlags[0] = 0;
  7524.         m_apFlags[1] = 0;
  7525.         m_pGameType = "CTF";
  7526.         m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS;
  7527.  }
  7528.  
  7529. -// balancing
  7530. -bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID)
  7531. +bool CGameControllerCTF::OnEntity(int Index, vec2 Pos)
  7532.  {
  7533. -       CCharacter* Character = GameServer()->m_apPlayers[ClientID]->GetCharacter();
  7534. -       if(Character)
  7535. -       {
  7536. -               for(int fi = 0; fi < 2; fi++)
  7537. -               {
  7538. -                       CFlag *F = m_apFlags[fi];
  7539. -                       if(F->m_pCarryingCharacter == Character)
  7540. -                               return false;
  7541. -               }
  7542. -       }
  7543. +       if(IGameController::OnEntity(Index, Pos))
  7544. +               return true;
  7545. +
  7546. +       int Team = -1;
  7547. +       if(Index == ENTITY_FLAGSTAND_RED) Team = TEAM_RED;
  7548. +       if(Index == ENTITY_FLAGSTAND_BLUE) Team = TEAM_BLUE;
  7549. +       if(Team == -1 || m_apFlags[Team])
  7550. +               return false;
  7551. +
  7552. +       CFlag *F = new CFlag(&GameServer()->m_World, Team);
  7553. +       F->m_StandPos = Pos;
  7554. +       F->m_Pos = Pos;
  7555. +       m_apFlags[Team] = F;
  7556. +       GameServer()->m_World.InsertEntity(F);
  7557.         return true;
  7558.  }
  7559.  
  7560. -// event
  7561. -int CGameControllerCTF::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int WeaponID)
  7562. +int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID)
  7563.  {
  7564.         IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID);
  7565.         int HadFlag = 0;
  7566. @@ -65,48 +66,45 @@
  7567.         return HadFlag;
  7568.  }
  7569.  
  7570. -bool CGameControllerCTF::OnEntity(int Index, vec2 Pos)
  7571. +void CGameControllerCTF::DoWincheck()
  7572.  {
  7573. -       if(IGameController::OnEntity(Index, Pos))
  7574. -               return true;
  7575. -
  7576. -       int Team = -1;
  7577. -       if(Index == ENTITY_FLAGSTAND_RED) Team = TEAM_RED;
  7578. -       if(Index == ENTITY_FLAGSTAND_BLUE) Team = TEAM_BLUE;
  7579. -       if(Team == -1 || m_apFlags[Team])
  7580. -               return false;
  7581. -
  7582. -       CFlag *F = new CFlag(&GameServer()->m_World, Team);
  7583. -       F->m_StandPos = Pos;
  7584. -       F->m_Pos = Pos;
  7585. -       m_apFlags[Team] = F;
  7586. -       GameServer()->m_World.InsertEntity(F);
  7587. -       return true;
  7588. +       if(m_GameOverTick == -1 && !m_Warmup)
  7589. +       {
  7590. +               // check score win condition
  7591. +               if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
  7592. +                       (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  7593. +               {
  7594. +                       if(m_SuddenDeath)
  7595. +                       {
  7596. +                               if(m_aTeamscore[TEAM_RED]/100 != m_aTeamscore[TEAM_BLUE]/100)
  7597. +                                       EndRound();
  7598. +                       }
  7599. +                       else
  7600. +                       {
  7601. +                               if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
  7602. +                                       EndRound();
  7603. +                               else
  7604. +                                       m_SuddenDeath = 1;
  7605. +                       }
  7606. +               }
  7607. +       }
  7608.  }
  7609.  
  7610. -// game
  7611. -void CGameControllerCTF::DoWincheckMatch()
  7612. +bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID)
  7613.  {
  7614. -       // check score win condition
  7615. -       if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
  7616. -               (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  7617. +       CCharacter* Character = GameServer()->m_apPlayers[ClientID]->GetCharacter();
  7618. +       if(Character)
  7619.         {
  7620. -               if(m_SuddenDeath)
  7621. -               {
  7622. -                       if(m_aTeamscore[TEAM_RED]/100 != m_aTeamscore[TEAM_BLUE]/100)
  7623. -                               EndMatch();
  7624. -               }
  7625. -               else
  7626. +               for(int fi = 0; fi < 2; fi++)
  7627.                 {
  7628. -                       if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
  7629. -                               EndMatch();
  7630. -                       else
  7631. -                               m_SuddenDeath = 1;
  7632. +                       CFlag *F = m_apFlags[fi];
  7633. +                       if(F->m_pCarryingCharacter == Character)
  7634. +                               return false;
  7635.                 }
  7636.         }
  7637. +       return true;
  7638.  }
  7639.  
  7640. -// general
  7641.  void CGameControllerCTF::Snap(int SnappingClient)
  7642.  {
  7643.         IGameController::Snap(SnappingClient);
  7644. @@ -118,7 +116,6 @@
  7645.         pGameDataObj->m_TeamscoreRed = m_aTeamscore[TEAM_RED];
  7646.         pGameDataObj->m_TeamscoreBlue = m_aTeamscore[TEAM_BLUE];
  7647.  
  7648. -       pGameDataObj->m_FlagDropTickRed = 0;
  7649.         if(m_apFlags[TEAM_RED])
  7650.         {
  7651.                 if(m_apFlags[TEAM_RED]->m_AtStand)
  7652. @@ -126,14 +123,10 @@
  7653.                 else if(m_apFlags[TEAM_RED]->m_pCarryingCharacter && m_apFlags[TEAM_RED]->m_pCarryingCharacter->GetPlayer())
  7654.                         pGameDataObj->m_FlagCarrierRed = m_apFlags[TEAM_RED]->m_pCarryingCharacter->GetPlayer()->GetCID();
  7655.                 else
  7656. -               {
  7657.                         pGameDataObj->m_FlagCarrierRed = FLAG_TAKEN;
  7658. -                       pGameDataObj->m_FlagDropTickRed = m_apFlags[TEAM_RED]->m_DropTick;
  7659. -               }
  7660.         }
  7661.         else
  7662.                 pGameDataObj->m_FlagCarrierRed = FLAG_MISSING;
  7663. -       pGameDataObj->m_FlagDropTickBlue = 0;
  7664.         if(m_apFlags[TEAM_BLUE])
  7665.         {
  7666.                 if(m_apFlags[TEAM_BLUE]->m_AtStand)
  7667. @@ -141,10 +134,7 @@
  7668.                 else if(m_apFlags[TEAM_BLUE]->m_pCarryingCharacter && m_apFlags[TEAM_BLUE]->m_pCarryingCharacter->GetPlayer())
  7669.                         pGameDataObj->m_FlagCarrierBlue = m_apFlags[TEAM_BLUE]->m_pCarryingCharacter->GetPlayer()->GetCID();
  7670.                 else
  7671. -               {
  7672.                         pGameDataObj->m_FlagCarrierBlue = FLAG_TAKEN;
  7673. -                       pGameDataObj->m_FlagDropTickBlue = m_apFlags[TEAM_BLUE]->m_DropTick;
  7674. -               }
  7675.         }
  7676.         else
  7677.                 pGameDataObj->m_FlagCarrierBlue = FLAG_MISSING;
  7678. @@ -262,8 +252,7 @@
  7679.                                                 if(!pPlayer)
  7680.                                                         continue;
  7681.  
  7682. -                                               if((pPlayer->GetTeam() == TEAM_SPECTATORS || pPlayer->m_DeadSpecMode) && pPlayer->GetSpectatorID() != SPEC_FREEVIEW &&
  7683. -                                                       GameServer()->m_apPlayers[pPlayer->GetSpectatorID()] && GameServer()->m_apPlayers[pPlayer->GetSpectatorID()]->GetTeam() == fi)
  7684. +                                               if(pPlayer->GetTeam() == TEAM_SPECTATORS && pPlayer->m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[pPlayer->m_SpectatorID] && GameServer()->m_apPlayers[pPlayer->m_SpectatorID]->GetTeam() == fi)
  7685.                                                         GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
  7686.                                                 else if(pPlayer->GetTeam() == fi)
  7687.                                                         GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
  7688. diff -Naur ../teeworlds/src/game/server/gamemodes/ctf.h src/game/server/gamemodes/ctf.h
  7689. --- ../teeworlds/src/game/server/gamemodes/ctf.h        2012-06-26 16:53:53.396862075 +1000
  7690. +++ src/game/server/gamemodes/ctf.h     2012-07-08 19:28:03.418259861 +1000
  7691. @@ -7,24 +7,17 @@
  7692.  
  7693.  class CGameControllerCTF : public IGameController
  7694.  {
  7695. -       // balancing
  7696. -       virtual bool CanBeMovedOnBalance(int ClientID);
  7697. -
  7698. -       // game
  7699. +public:
  7700.         class CFlag *m_apFlags[2];
  7701.  
  7702. -       virtual void DoWincheckMatch();
  7703. -
  7704. -public:
  7705.         CGameControllerCTF(class CGameContext *pGameServer);
  7706. -      
  7707. -       // event
  7708. -       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7709. -       virtual bool OnEntity(int Index, vec2 Pos);
  7710. -
  7711. -       // general
  7712. +       virtual void DoWincheck();
  7713. +       virtual bool CanBeMovedOnBalance(int ClientID);
  7714.         virtual void Snap(int SnappingClient);
  7715.         virtual void Tick();
  7716. +
  7717. +       virtual bool OnEntity(int Index, vec2 Pos);
  7718. +       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7719.  };
  7720.  
  7721.  #endif
  7722. diff -Naur ../teeworlds/src/game/server/gamemodes/dm.cpp src/game/server/gamemodes/dm.cpp
  7723. --- ../teeworlds/src/game/server/gamemodes/dm.cpp       2012-06-26 16:53:53.396862075 +1000
  7724. +++ src/game/server/gamemodes/dm.cpp    2012-07-08 19:28:03.418259861 +1000
  7725. @@ -3,8 +3,13 @@
  7726.  #include "dm.h"
  7727.  
  7728.  
  7729. -CGameControllerDM::CGameControllerDM(CGameContext *pGameServer)
  7730. +CGameControllerDM::CGameControllerDM(class CGameContext *pGameServer)
  7731.  : IGameController(pGameServer)
  7732.  {
  7733.         m_pGameType = "DM";
  7734.  }
  7735. +
  7736. +void CGameControllerDM::Tick()
  7737. +{
  7738. +       IGameController::Tick();
  7739. +}
  7740. diff -Naur ../teeworlds/src/game/server/gamemodes/dm.h src/game/server/gamemodes/dm.h
  7741. --- ../teeworlds/src/game/server/gamemodes/dm.h 2012-06-26 16:53:53.396862075 +1000
  7742. +++ src/game/server/gamemodes/dm.h      2012-07-08 19:28:03.418259861 +1000
  7743. @@ -8,6 +8,6 @@
  7744.  {
  7745.  public:
  7746.         CGameControllerDM(class CGameContext *pGameServer);
  7747. +       virtual void Tick();
  7748.  };
  7749. -
  7750.  #endif
  7751. diff -Naur ../teeworlds/src/game/server/gamemodes/lms.cpp src/game/server/gamemodes/lms.cpp
  7752. --- ../teeworlds/src/game/server/gamemodes/lms.cpp      2012-06-26 16:53:53.396862075 +1000
  7753. +++ src/game/server/gamemodes/lms.cpp   1970-01-01 10:00:00.000000000 +1000
  7754. @@ -1,70 +0,0 @@
  7755. -/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  7756. -/* If you are missing that file, acquire a complete release at teeworlds.com.                */
  7757. -#include <engine/shared/config.h>
  7758. -
  7759. -#include <game/server/entities/character.h>
  7760. -#include <game/server/gamecontext.h>
  7761. -#include <game/server/player.h>
  7762. -#include "lms.h"
  7763. -
  7764. -CGameControllerLMS::CGameControllerLMS(CGameContext *pGameServer) : IGameController(pGameServer)
  7765. -{
  7766. -       m_pGameType = "LMS";
  7767. -       m_GameFlags = GAMEFLAG_SURVIVAL;
  7768. -}
  7769. -
  7770. -// event
  7771. -int CGameControllerLMS::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int Weapon)
  7772. -{
  7773. -       // update spectator modes for dead players in survival
  7774. -       if(m_GameFlags&GAMEFLAG_SURVIVAL)
  7775. -       {
  7776. -               for(int i = 0; i < MAX_CLIENTS; ++i)
  7777. -                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_DeadSpecMode)
  7778. -                               GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
  7779. -       }
  7780. -
  7781. -       return 0;
  7782. -}
  7783. -
  7784. -// game
  7785. -void CGameControllerLMS::DoWincheckRound()
  7786. -{
  7787. -       // check for time based win
  7788. -       if(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)
  7789. -       {
  7790. -               for(int i = 0; i < MAX_CLIENTS; ++i)
  7791. -               {
  7792. -                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS &&
  7793. -                               (!GameServer()->m_apPlayers[i]->m_RespawnDisabled ||
  7794. -                               (GameServer()->m_apPlayers[i]->GetCharacter() && GameServer()->m_apPlayers[i]->GetCharacter()->IsAlive())))
  7795. -                               GameServer()->m_apPlayers[i]->m_Score++;
  7796. -               }
  7797. -
  7798. -               EndRound();
  7799. -       }
  7800. -       else
  7801. -       {
  7802. -               // check for survival win
  7803. -               CPlayer *pAlivePlayer = 0;
  7804. -               int AlivePlayerCount = 0;
  7805. -               for(int i = 0; i < MAX_CLIENTS; ++i)
  7806. -               {
  7807. -                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS &&
  7808. -                               (!GameServer()->m_apPlayers[i]->m_RespawnDisabled ||
  7809. -                               (GameServer()->m_apPlayers[i]->GetCharacter() && GameServer()->m_apPlayers[i]->GetCharacter()->IsAlive())))
  7810. -                       {
  7811. -                               ++AlivePlayerCount;
  7812. -                               pAlivePlayer = GameServer()->m_apPlayers[i];
  7813. -                       }
  7814. -               }
  7815. -
  7816. -               if(AlivePlayerCount == 0)               // no winner
  7817. -                       EndRound();
  7818. -               else if(AlivePlayerCount == 1)  // 1 winner
  7819. -               {
  7820. -                       pAlivePlayer->m_Score++;
  7821. -                       EndRound();
  7822. -               }
  7823. -       }
  7824. -}
  7825. diff -Naur ../teeworlds/src/game/server/gamemodes/lms.h src/game/server/gamemodes/lms.h
  7826. --- ../teeworlds/src/game/server/gamemodes/lms.h        2012-06-26 16:53:53.396862075 +1000
  7827. +++ src/game/server/gamemodes/lms.h     1970-01-01 10:00:00.000000000 +1000
  7828. @@ -1,19 +0,0 @@
  7829. -/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  7830. -/* If you are missing that file, acquire a complete release at teeworlds.com.                */
  7831. -#ifndef GAME_SERVER_GAMEMODES_LMS_H
  7832. -#define GAME_SERVER_GAMEMODES_LMS_H
  7833. -#include <game/server/gamecontroller.h>
  7834. -
  7835. -class CGameControllerLMS : public IGameController
  7836. -{
  7837. -public:
  7838. -       CGameControllerLMS(class CGameContext *pGameServer);
  7839. -
  7840. -       // event
  7841. -       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7842. -
  7843. -       // game
  7844. -       virtual void DoWincheckRound();
  7845. -};
  7846. -
  7847. -#endif
  7848. diff -Naur ../teeworlds/src/game/server/gamemodes/mod.cpp src/game/server/gamemodes/mod.cpp
  7849. --- ../teeworlds/src/game/server/gamemodes/mod.cpp      2012-06-26 16:53:53.396862075 +1000
  7850. +++ src/game/server/gamemodes/mod.cpp   2012-07-08 19:28:03.418259861 +1000
  7851. @@ -7,7 +7,7 @@
  7852.  {
  7853.         // Exchange this to a string that identifies your game mode.
  7854.         // DM, TDM and CTF are reserved for teeworlds original modes.
  7855. -       m_pGameType = "MOD";
  7856. +       m_pGameType = "BBM";
  7857.  
  7858.         //m_GameFlags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode
  7859.  }
  7860. diff -Naur ../teeworlds/src/game/server/gamemodes/sur.cpp src/game/server/gamemodes/sur.cpp
  7861. --- ../teeworlds/src/game/server/gamemodes/sur.cpp      2012-06-26 16:53:53.396862075 +1000
  7862. +++ src/game/server/gamemodes/sur.cpp   1970-01-01 10:00:00.000000000 +1000
  7863. @@ -1,62 +0,0 @@
  7864. -/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  7865. -/* If you are missing that file, acquire a complete release at teeworlds.com.                */
  7866. -#include <engine/shared/config.h>
  7867. -
  7868. -#include <game/server/entities/character.h>
  7869. -#include <game/server/gamecontext.h>
  7870. -#include <game/server/player.h>
  7871. -#include "sur.h"
  7872. -
  7873. -CGameControllerSUR::CGameControllerSUR(CGameContext *pGameServer) : IGameController(pGameServer)
  7874. -{
  7875. -       m_pGameType = "SUR";
  7876. -       m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_SURVIVAL;
  7877. -}
  7878. -
  7879. -// game
  7880. -void CGameControllerSUR::DoWincheckRound()
  7881. -{
  7882. -       int Count[2] = {0};
  7883. -       for(int i = 0; i < MAX_CLIENTS; ++i)
  7884. -       {
  7885. -               if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS &&
  7886. -                       (!GameServer()->m_apPlayers[i]->m_RespawnDisabled ||
  7887. -                       (GameServer()->m_apPlayers[i]->GetCharacter() && GameServer()->m_apPlayers[i]->GetCharacter()->IsAlive())))
  7888. -                       ++Count[GameServer()->m_apPlayers[i]->GetTeam()];
  7889. -       }
  7890. -
  7891. -       if(Count[TEAM_RED]+Count[TEAM_BLUE] == 0 || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_GameStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
  7892. -       {
  7893. -               ++m_aTeamscore[TEAM_BLUE];
  7894. -               ++m_aTeamscore[TEAM_RED];
  7895. -               EndRound();
  7896. -       }
  7897. -       else if(Count[TEAM_RED] == 0)
  7898. -       {
  7899. -               ++m_aTeamscore[TEAM_BLUE];
  7900. -               EndRound();
  7901. -       }
  7902. -       else if(Count[TEAM_BLUE] == 0)
  7903. -       {
  7904. -               ++m_aTeamscore[TEAM_RED];
  7905. -               EndRound();
  7906. -       }
  7907. -}
  7908. -
  7909. -// general
  7910. -void CGameControllerSUR::Snap(int SnappingClient)
  7911. -{
  7912. -       IGameController::Snap(SnappingClient);
  7913. -
  7914. -       CNetObj_GameData *pGameDataObj = (CNetObj_GameData *)Server()->SnapNewItem(NETOBJTYPE_GAMEDATA, 0, sizeof(CNetObj_GameData));
  7915. -       if(!pGameDataObj)
  7916. -               return;
  7917. -
  7918. -       pGameDataObj->m_TeamscoreRed = m_aTeamscore[TEAM_RED];
  7919. -       pGameDataObj->m_TeamscoreBlue = m_aTeamscore[TEAM_BLUE];
  7920. -
  7921. -       pGameDataObj->m_FlagCarrierRed = 0;
  7922. -       pGameDataObj->m_FlagCarrierBlue = 0;
  7923. -       pGameDataObj->m_FlagDropTickRed = 0;
  7924. -       pGameDataObj->m_FlagDropTickBlue = 0;
  7925. -}
  7926. diff -Naur ../teeworlds/src/game/server/gamemodes/sur.h src/game/server/gamemodes/sur.h
  7927. --- ../teeworlds/src/game/server/gamemodes/sur.h        2012-06-26 16:53:53.396862075 +1000
  7928. +++ src/game/server/gamemodes/sur.h     1970-01-01 10:00:00.000000000 +1000
  7929. @@ -1,19 +0,0 @@
  7930. -/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  7931. -/* If you are missing that file, acquire a complete release at teeworlds.com.                */
  7932. -#ifndef GAME_SERVER_GAMEMODES_SUR_H
  7933. -#define GAME_SERVER_GAMEMODES_SUR_H
  7934. -#include <game/server/gamecontroller.h>
  7935. -
  7936. -class CGameControllerSUR : public IGameController
  7937. -{
  7938. -public:
  7939. -       CGameControllerSUR(class CGameContext *pGameServer);
  7940. -
  7941. -       // game
  7942. -       virtual void DoWincheckRound();
  7943. -
  7944. -       // general
  7945. -       virtual void Snap(int SnappingClient);
  7946. -};
  7947. -
  7948. -#endif
  7949. diff -Naur ../teeworlds/src/game/server/gamemodes/tdm.cpp src/game/server/gamemodes/tdm.cpp
  7950. --- ../teeworlds/src/game/server/gamemodes/tdm.cpp      2012-06-26 16:53:53.396862075 +1000
  7951. +++ src/game/server/gamemodes/tdm.cpp   2012-07-08 19:28:03.418259861 +1000
  7952. @@ -3,7 +3,6 @@
  7953.  #include <engine/shared/config.h>
  7954.  
  7955.  #include <game/server/entities/character.h>
  7956. -#include <game/server/gamecontext.h>
  7957.  #include <game/server/player.h>
  7958.  #include "tdm.h"
  7959.  
  7960. @@ -13,7 +12,6 @@
  7961.         m_GameFlags = GAMEFLAG_TEAMS;
  7962.  }
  7963.  
  7964. -// event
  7965.  int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
  7966.  {
  7967.         IGameController::OnCharacterDeath(pVictim, pKiller, Weapon);
  7968. @@ -33,7 +31,6 @@
  7969.         return 0;
  7970.  }
  7971.  
  7972. -// general
  7973.  void CGameControllerTDM::Snap(int SnappingClient)
  7974.  {
  7975.         IGameController::Snap(SnappingClient);
  7976. @@ -47,6 +44,9 @@
  7977.  
  7978.         pGameDataObj->m_FlagCarrierRed = 0;
  7979.         pGameDataObj->m_FlagCarrierBlue = 0;
  7980. -       pGameDataObj->m_FlagDropTickRed = 0;
  7981. -       pGameDataObj->m_FlagDropTickBlue = 0;
  7982. +}
  7983. +
  7984. +void CGameControllerTDM::Tick()
  7985. +{
  7986. +       IGameController::Tick();
  7987.  }
  7988. diff -Naur ../teeworlds/src/game/server/gamemodes/tdm.h src/game/server/gamemodes/tdm.h
  7989. --- ../teeworlds/src/game/server/gamemodes/tdm.h        2012-06-26 16:53:53.396862075 +1000
  7990. +++ src/game/server/gamemodes/tdm.h     2012-07-08 19:28:03.418259861 +1000
  7991. @@ -9,11 +9,8 @@
  7992.  public:
  7993.         CGameControllerTDM(class CGameContext *pGameServer);
  7994.  
  7995. -       // event
  7996. -       virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  7997. -
  7998. -       // general
  7999. +       int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
  8000.         virtual void Snap(int SnappingClient);
  8001. +       virtual void Tick();
  8002.  };
  8003. -
  8004.  #endif
  8005. diff -Naur ../teeworlds/src/game/server/gameworld.cpp src/game/server/gameworld.cpp
  8006. --- ../teeworlds/src/game/server/gameworld.cpp  2012-06-26 16:53:53.396862075 +1000
  8007. +++ src/game/server/gameworld.cpp       2012-07-08 19:42:32.842259599 +1000
  8008. @@ -1,12 +1,12 @@
  8009.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  8010.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  8011.  
  8012. -#include "entities/character.h"
  8013. +#include "gameworld.h"
  8014.  #include "entity.h"
  8015.  #include "gamecontext.h"
  8016. -#include "gamecontroller.h"
  8017. -#include "gameworld.h"
  8018. -
  8019. +#include <algorithm>
  8020. +#include <utility>
  8021. +#include <engine/shared/config.h>
  8022.  
  8023.  //////////////////////////////////////////////////
  8024.  // game world
  8025. @@ -128,7 +128,7 @@
  8026.                 }
  8027.         RemoveEntities();
  8028.  
  8029. -       GameServer()->m_pController->OnReset();
  8030. +       GameServer()->m_pController->PostReset();
  8031.         RemoveEntities();
  8032.  
  8033.         m_ResetRequested = false;
  8034. @@ -150,6 +150,75 @@
  8035.                 }
  8036.  }
  8037.  
  8038. +bool distCompare(std::pair<float,int> a, std::pair<float,int> b)
  8039. +{
  8040. +       return (a.first < b.first);
  8041. +}
  8042. +
  8043. +void CGameWorld::UpdatePlayerMaps()
  8044. +{
  8045. +       if (Server()->Tick() % g_Config.m_SvMapUpdateRate != 0) return;
  8046. +
  8047. +       std::pair<float,int> dist[MAX_CLIENTS];
  8048. +       for (int i = 0; i < MAX_CLIENTS; i++)
  8049. +       {
  8050. +               if (!Server()->ClientIngame(i)) continue;
  8051. +               int* map = Server()->GetIdMap(i);
  8052. +
  8053. +               // compute distances
  8054. +               for (int j = 0; j < MAX_CLIENTS; j++)
  8055. +               {
  8056. +                       dist[j].second = j;
  8057. +                       dist[j].first = 1e10;
  8058. +                       if (!Server()->ClientIngame(j))
  8059. +                               continue;
  8060. +                       CCharacter* ch = GameServer()->m_apPlayers[j]->GetCharacter();
  8061. +                       if (!ch)
  8062. +                               continue;
  8063. +                       dist[j].first = distance(GameServer()->m_apPlayers[i]->m_ViewPos, GameServer()->m_apPlayers[j]->m_ViewPos);
  8064. +               }
  8065. +
  8066. +               // always send the player himself
  8067. +               dist[i].first = 0;
  8068. +
  8069. +               // compute reverse map
  8070. +               int rMap[MAX_CLIENTS];
  8071. +               for (int j = 0; j < MAX_CLIENTS; j++)
  8072. +               {
  8073. +                       rMap[j] = -1;
  8074. +               }
  8075. +               for (int j = 0; j < VANILLA_MAX_CLIENTS; j++)
  8076. +               {
  8077. +                       if (map[j] == -1) continue;
  8078. +                       if (dist[map[j]].first > 1e9) map[j] = -1;
  8079. +                       else rMap[map[j]] = j;
  8080. +               }
  8081. +
  8082. +               std::nth_element(&dist[0], &dist[VANILLA_MAX_CLIENTS - 1], &dist[MAX_CLIENTS], distCompare);
  8083. +
  8084. +               int mapc = 0;
  8085. +               int demand = 0;
  8086. +               for (int j = 0; j < VANILLA_MAX_CLIENTS - 1; j++)
  8087. +               {
  8088. +                       int k = dist[j].second;
  8089. +                       if (rMap[k] != -1 || dist[j].first > 1e9) continue;
  8090. +                       while (mapc < VANILLA_MAX_CLIENTS && map[mapc] != -1) mapc++;
  8091. +                       if (mapc < VANILLA_MAX_CLIENTS - 1)
  8092. +                               map[mapc] = k;
  8093. +                       else
  8094. +                               if (dist[j].first < 1300) // dont bother freeing up space for players which are too far to be displayed anyway
  8095. +                                       demand++;
  8096. +               }
  8097. +               for (int j = MAX_CLIENTS - 1; j > VANILLA_MAX_CLIENTS - 2; j--)
  8098. +               {
  8099. +                       int k = dist[j].second;
  8100. +                       if (rMap[k] != -1 && demand-- > 0)
  8101. +                               map[rMap[k]] = -1;
  8102. +               }
  8103. +               map[VANILLA_MAX_CLIENTS - 1] = -1; // player with empty name to say chat msgs
  8104. +       }
  8105. +}
  8106. +
  8107.  void CGameWorld::Tick()
  8108.  {
  8109.         if(m_ResetRequested)
  8110. @@ -157,6 +226,8 @@
  8111.  
  8112.         if(!m_Paused)
  8113.         {
  8114. +               if(GameServer()->m_pController->IsForceBalanced())
  8115. +                       GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
  8116.                 // update all objects
  8117.                 for(int i = 0; i < NUM_ENTTYPES; i++)
  8118.                         for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
  8119. @@ -174,7 +245,7 @@
  8120.                                 pEnt = m_pNextTraverseEntity;
  8121.                         }
  8122.         }
  8123. -       else if(GameServer()->m_pController->IsGamePaused())
  8124. +       else
  8125.         {
  8126.                 // update all objects
  8127.                 for(int i = 0; i < NUM_ENTTYPES; i++)
  8128. @@ -187,8 +258,9 @@
  8129.         }
  8130.  
  8131.         RemoveEntities();
  8132. -}
  8133.  
  8134. +       UpdatePlayerMaps();
  8135. +}
  8136.  
  8137.  // TODO: should be more general
  8138.  CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2& NewPos, CEntity *pNotThis)
  8139. diff -Naur ../teeworlds/src/game/server/gameworld.h src/game/server/gameworld.h
  8140. --- ../teeworlds/src/game/server/gameworld.h    2012-06-26 16:53:53.396862075 +1000
  8141. +++ src/game/server/gameworld.h 2012-07-08 19:28:03.418259861 +1000
  8142. @@ -36,6 +36,8 @@
  8143.         class CGameContext *m_pGameServer;
  8144.         class IServer *m_pServer;
  8145.  
  8146. +       void UpdatePlayerMaps();
  8147. +
  8148.  public:
  8149.         class CGameContext *GameServer() { return m_pGameServer; }
  8150.         class IServer *Server() { return m_pServer; }
  8151. diff -Naur ../teeworlds/src/game/server/player.cpp src/game/server/player.cpp
  8152. --- ../teeworlds/src/game/server/player.cpp     2012-06-26 16:53:53.400861537 +1000
  8153. +++ src/game/server/player.cpp  2012-07-08 19:44:28.473761216 +1000
  8154. @@ -1,9 +1,7 @@
  8155.  /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  8156.  /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  8157. -
  8158. -#include "entities/character.h"
  8159. -#include "gamecontext.h"
  8160. -#include "gamecontroller.h"
  8161. +#include <new>
  8162. +#include <engine/shared/config.h>
  8163.  #include "player.h"
  8164.  
  8165.  
  8166. @@ -11,23 +9,28 @@
  8167.  
  8168.  IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
  8169.  
  8170. -CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy)
  8171. +CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
  8172.  {
  8173. +       m_Muted = 0;
  8174.         m_pGameServer = pGameServer;
  8175.         m_RespawnTick = Server()->Tick();
  8176.         m_DieTick = Server()->Tick();
  8177.         m_ScoreStartTick = Server()->Tick();
  8178.         m_pCharacter = 0;
  8179.         m_ClientID = ClientID;
  8180. -       m_Team = GameServer()->m_pController->GetStartTeam();
  8181. +       m_Team = GameServer()->m_pController->ClampTeam(Team);
  8182.         m_SpectatorID = SPEC_FREEVIEW;
  8183.         m_LastActionTick = Server()->Tick();
  8184. +       slot3 = 0;
  8185. +       int* idMap = Server()->GetIdMap(ClientID);
  8186. +       for (int i = 1;i < VANILLA_MAX_CLIENTS;i++)
  8187. +       {
  8188. +           idMap[i] = -1;
  8189. +       }
  8190. +       idMap[0] = ClientID;
  8191. +
  8192. +
  8193.         m_TeamChangeTick = Server()->Tick();
  8194. -       m_Dummy = Dummy;
  8195. -       m_IsReadyToPlay = !GameServer()->m_pController->IsPlayerReadyMode();
  8196. -       m_RespawnDisabled = GameServer()->m_pController->GetStartRespawnState();
  8197. -       m_DeadSpecMode = false;
  8198. -       m_Spawning = 0;
  8199.  }
  8200.  
  8201.  CPlayer::~CPlayer()
  8202. @@ -38,11 +41,18 @@
  8203.  
  8204.  void CPlayer::Tick()
  8205.  {
  8206. -       if(!IsDummy() && !Server()->ClientIngame(m_ClientID))
  8207. +#ifdef CONF_DEBUG
  8208. +       if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
  8209. +#endif
  8210. +       if(!Server()->ClientIngame(m_ClientID))
  8211.                 return;
  8212.  
  8213.         Server()->SetClientScore(m_ClientID, m_Score);
  8214.  
  8215. +       if(m_Muted != 0)
  8216. +       {
  8217. +               m_Muted--;
  8218. +       }
  8219.         // do latency stuff
  8220.         {
  8221.                 IServer::CClientInfo Info;
  8222. @@ -64,24 +74,25 @@
  8223.                 }
  8224.         }
  8225.  
  8226. -       if(m_pCharacter && !m_pCharacter->IsAlive())
  8227. -       {
  8228. -               delete m_pCharacter;
  8229. -               m_pCharacter = 0;
  8230. -       }
  8231. -
  8232. -       if(!GameServer()->m_pController->IsGamePaused())
  8233. +       if(!GameServer()->m_World.m_Paused)
  8234.         {
  8235.                 if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
  8236.                         m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));
  8237.  
  8238. -               if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick() && !m_DeadSpecMode)
  8239. -                       Respawn();
  8240. +               if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
  8241. +                       m_Spawning = true;
  8242.  
  8243.                 if(m_pCharacter)
  8244.                 {
  8245.                         if(m_pCharacter->IsAlive())
  8246. +                       {
  8247.                                 m_ViewPos = m_pCharacter->m_Pos;
  8248. +                       }
  8249. +                       else
  8250. +                       {
  8251. +                               delete m_pCharacter;
  8252. +                               m_pCharacter = 0;
  8253. +                       }
  8254.                 }
  8255.                 else if(m_Spawning && m_RespawnTick <= Server()->Tick())
  8256.                         TryRespawn();
  8257. @@ -108,17 +119,24 @@
  8258.                 }
  8259.         }
  8260.  
  8261. -       // update view pos for spectators and dead players
  8262. -       if((m_Team == TEAM_SPECTATORS || m_DeadSpecMode) && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
  8263. +       // update view pos for spectators
  8264. +       if(m_Team == TEAM_SPECTATORS && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
  8265.                 m_ViewPos = GameServer()->m_apPlayers[m_SpectatorID]->m_ViewPos;
  8266.  }
  8267.  
  8268.  void CPlayer::Snap(int SnappingClient)
  8269.  {
  8270. -       if(!IsDummy() && !Server()->ClientIngame(m_ClientID))
  8271. +#ifdef CONF_DEBUG
  8272. +       if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
  8273. +#endif
  8274. +       if(!Server()->ClientIngame(m_ClientID))
  8275.                 return;
  8276.  
  8277. -       CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
  8278. +       int id = m_ClientID;
  8279. +       if (!Server()->Translate(id, SnappingClient)) return;
  8280. +
  8281. +       CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
  8282. +
  8283.         if(!pClientInfo)
  8284.                 return;
  8285.  
  8286. @@ -130,27 +148,20 @@
  8287.         pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
  8288.         pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
  8289.  
  8290. -       CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo)));
  8291. +       CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, id, sizeof(CNetObj_PlayerInfo)));
  8292.         if(!pPlayerInfo)
  8293.                 return;
  8294.  
  8295. -       pPlayerInfo->m_PlayerFlags = m_PlayerFlags&PLAYERFLAG_CHATTING;
  8296. -       if(!GameServer()->m_pController->IsPlayerReadyMode() || m_IsReadyToPlay)
  8297. -               pPlayerInfo->m_PlayerFlags |= PLAYERFLAG_READY;
  8298. -       if(m_RespawnDisabled && (!GetCharacter() || !GetCharacter()->IsAlive()))
  8299. -               pPlayerInfo->m_PlayerFlags |= PLAYERFLAG_DEAD;
  8300. -       if(SnappingClient != -1 && (m_Team == TEAM_SPECTATORS || m_DeadSpecMode) && SnappingClient == m_SpectatorID)
  8301. -               pPlayerInfo->m_PlayerFlags |= PLAYERFLAG_WATCHING;
  8302.         pPlayerInfo->m_Latency = SnappingClient == -1 ? m_Latency.m_Min : GameServer()->m_apPlayers[SnappingClient]->m_aActLatency[m_ClientID];
  8303.         pPlayerInfo->m_Local = 0;
  8304. -       pPlayerInfo->m_ClientID = m_ClientID;
  8305. +       pPlayerInfo->m_ClientID = id;
  8306.         pPlayerInfo->m_Score = m_Score;
  8307.         pPlayerInfo->m_Team = m_Team;
  8308.  
  8309.         if(m_ClientID == SnappingClient)
  8310.                 pPlayerInfo->m_Local = 1;
  8311.  
  8312. -       if(m_ClientID == SnappingClient && (m_Team == TEAM_SPECTATORS || m_DeadSpecMode))
  8313. +       if(m_ClientID == SnappingClient && m_Team == TEAM_SPECTATORS)
  8314.         {
  8315.                 CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(CNetObj_SpectatorInfo)));
  8316.                 if(!pSpectatorInfo)
  8317. @@ -162,23 +173,40 @@
  8318.         }
  8319.  }
  8320.  
  8321. -void CPlayer::OnDisconnect()
  8322. +void CPlayer::FakeSnap(int SnappingClient)
  8323. +{
  8324. +       IServer::CClientInfo info;
  8325. +       Server()->GetClientInfo(SnappingClient, &info);
  8326. +       if (info.m_CustClt)
  8327. +               return;
  8328. +
  8329. +       int id = VANILLA_MAX_CLIENTS - 1;
  8330. +
  8331. +       CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
  8332. +
  8333. +       if(!pClientInfo)
  8334. +               return;
  8335. +
  8336. +       StrToInts(&pClientInfo->m_Name0, 4, " ");
  8337. +       StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientID));
  8338. +       StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
  8339. +}
  8340. +
  8341. +void CPlayer::OnDisconnect(const char *pReason)
  8342.  {
  8343.         KillCharacter();
  8344.  
  8345. -       if(m_Team != TEAM_SPECTATORS)
  8346. +       if(Server()->ClientIngame(m_ClientID))
  8347.         {
  8348. -               // update spectator modes
  8349. -               for(int i = 0; i < MAX_CLIENTS; ++i)
  8350. -               {
  8351. -                       if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
  8352. -                       {
  8353. -                               if(GameServer()->m_apPlayers[i]->m_DeadSpecMode)
  8354. -                                       GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
  8355. -                               else
  8356. -                                       GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
  8357. -                       }
  8358. -               }
  8359. +               char aBuf[512];
  8360. +               if(pReason && *pReason)
  8361. +                       str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason);
  8362. +               else
  8363. +                       str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID));
  8364. +               GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  8365. +
  8366. +               //str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
  8367. +               GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "game", aBuf);
  8368.         }
  8369.  }
  8370.  
  8371. @@ -194,12 +222,6 @@
  8372.  
  8373.  void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
  8374.  {
  8375. -       if(GameServer()->m_World.m_Paused)
  8376. -       {
  8377. -               m_PlayerFlags = NewInput->m_PlayerFlags;
  8378. -               return;
  8379. -       }
  8380. -
  8381.         if(NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING)
  8382.         {
  8383.                 // skip the input if chat is active
  8384. @@ -220,7 +242,7 @@
  8385.                 m_pCharacter->OnDirectInput(NewInput);
  8386.  
  8387.         if(!m_pCharacter && m_Team != TEAM_SPECTATORS && (NewInput->m_Fire&1))
  8388. -               Respawn();
  8389. +               m_Spawning = true;
  8390.  
  8391.         // check for activity
  8392.         if(NewInput->m_Direction || m_LatestActivity.m_TargetX != NewInput->m_TargetX ||
  8393. @@ -252,98 +274,42 @@
  8394.  
  8395.  void CPlayer::Respawn()
  8396.  {
  8397. -       if(m_RespawnDisabled)
  8398. -       {
  8399. -               // enable spectate mode for dead players
  8400. -               m_DeadSpecMode = true;
  8401. -               m_IsReadyToPlay = true;
  8402. -               UpdateDeadSpecMode();
  8403. -               return;
  8404. -       }
  8405. -
  8406. -       m_DeadSpecMode = false;
  8407. -
  8408.         if(m_Team != TEAM_SPECTATORS)
  8409.                 m_Spawning = true;
  8410.  }
  8411.  
  8412. -bool CPlayer::SetSpectatorID(int SpectatorID)
  8413. -{
  8414. -       if(m_SpectatorID == SpectatorID || m_ClientID == SpectatorID)
  8415. -               return false;
  8416. -
  8417. -       if(m_Team == TEAM_SPECTATORS)
  8418. -       {
  8419. -               // check for freeview or if wanted player is playing
  8420. -               if(SpectatorID == SPEC_FREEVIEW || (GameServer()->m_apPlayers[SpectatorID] && GameServer()->m_apPlayers[SpectatorID]->GetTeam() != TEAM_SPECTATORS))
  8421. -               {
  8422. -                       m_SpectatorID = SpectatorID;
  8423. -                       return true;
  8424. -               }
  8425. -       }
  8426. -       else if(m_DeadSpecMode)
  8427. -       {
  8428. -               // check if wanted player can be followed
  8429. -               if(GameServer()->m_apPlayers[SpectatorID] && DeadCanFollow(GameServer()->m_apPlayers[SpectatorID]))
  8430. -               {
  8431. -                       m_SpectatorID = SpectatorID;
  8432. -                       return true;
  8433. -               }
  8434. -       }
  8435. -
  8436. -       return false;
  8437. -}
  8438. -
  8439. -bool CPlayer::DeadCanFollow(CPlayer *pPlayer) const
  8440. -{
  8441. -       // check if wanted player is in the same team and alive
  8442. -       return (!pPlayer->m_RespawnDisabled || (pPlayer->GetCharacter() && pPlayer->GetCharacter()->IsAlive())) && pPlayer->GetTeam() == m_Team;
  8443. -}
  8444. -
  8445. -void CPlayer::UpdateDeadSpecMode()
  8446. +void CPlayer::SetTeam(int Team, bool DoChatMsg)
  8447.  {
  8448. -       // check if actual spectator id is valid
  8449. -       if(m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID] && DeadCanFollow(GameServer()->m_apPlayers[m_SpectatorID]))
  8450. +       // clamp the team
  8451. +       Team = GameServer()->m_pController->ClampTeam(Team);
  8452. +       if(m_Team == Team)
  8453.                 return;
  8454.  
  8455. -       // find player to follow
  8456. -       for(int i = 0; i < MAX_CLIENTS; ++i)
  8457. +/*     char aBuf[512];
  8458. +       if(DoChatMsg)
  8459.         {
  8460. -               if(GameServer()->m_apPlayers[i] && DeadCanFollow(GameServer()->m_apPlayers[i]))
  8461. -               {
  8462. -                       m_SpectatorID = i;
  8463. -                       return;
  8464. -               }
  8465. -       }
  8466. -
  8467. -       // no one available to follow -> turn spectator mode off
  8468. -       m_DeadSpecMode = false;
  8469. -}
  8470. +               str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
  8471. +               GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  8472. +       }*/
  8473.  
  8474. -void CPlayer::SetTeam(int Team, bool DoChatMsg)
  8475. -{
  8476.         KillCharacter();
  8477.  
  8478.         m_Team = Team;
  8479.         m_LastActionTick = Server()->Tick();
  8480. -       m_SpectatorID = SPEC_FREEVIEW;
  8481. -       m_DeadSpecMode = false;
  8482. -      
  8483.         // we got to wait 0.5 secs before respawning
  8484.         m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  8485. -      
  8486. +       //str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
  8487. +       //GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  8488. +
  8489. +       GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
  8490. +
  8491.         if(Team == TEAM_SPECTATORS)
  8492.         {
  8493.                 // update spectator modes
  8494.                 for(int i = 0; i < MAX_CLIENTS; ++i)
  8495.                 {
  8496.                         if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
  8497. -                       {
  8498. -                               if(GameServer()->m_apPlayers[i]->m_DeadSpecMode)
  8499. -                                       GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
  8500. -                               else
  8501. -                                       GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
  8502. -                       }
  8503. +                               GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
  8504.                 }
  8505.         }
  8506.  }
  8507. diff -Naur ../teeworlds/src/game/server/player.h src/game/server/player.h
  8508. --- ../teeworlds/src/game/server/player.h       2012-06-26 16:53:53.400861537 +1000
  8509. +++ src/game/server/player.h    2012-07-08 19:42:32.954259163 +1000
  8510. @@ -3,15 +3,9 @@
  8511.  #ifndef GAME_SERVER_PLAYER_H
  8512.  #define GAME_SERVER_PLAYER_H
  8513.  
  8514. -#include "alloc.h"
  8515. -
  8516. -
  8517. -enum
  8518. -{
  8519. -       WEAPON_GAME = -3, // team switching etc
  8520. -       WEAPON_SELF = -2, // console kill command
  8521. -       WEAPON_WORLD = -1, // death tiles etc
  8522. -};
  8523. +// this include should perhaps be removed
  8524. +#include "entities/character.h"
  8525. +#include "gamecontext.h"
  8526.  
  8527.  // player object
  8528.  class CPlayer
  8529. @@ -19,7 +13,7 @@
  8530.         MACRO_ALLOC_POOL_ID()
  8531.  
  8532.  public:
  8533. -       CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy);
  8534. +       CPlayer(CGameContext *pGameServer, int ClientID, int Team);
  8535.         ~CPlayer();
  8536.  
  8537.         void Init(int CID);
  8538. @@ -29,15 +23,15 @@
  8539.         void SetTeam(int Team, bool DoChatMsg=true);
  8540.         int GetTeam() const { return m_Team; };
  8541.         int GetCID() const { return m_ClientID; };
  8542. -       bool IsDummy() const { return m_Dummy; }
  8543.  
  8544.         void Tick();
  8545.         void PostTick();
  8546.         void Snap(int SnappingClient);
  8547. +       void FakeSnap(int SnappingClient);
  8548.  
  8549.         void OnDirectInput(CNetObj_PlayerInput *NewInput);
  8550.         void OnPredictedInput(CNetObj_PlayerInput *NewInput);
  8551. -       void OnDisconnect();
  8552. +       void OnDisconnect(const char *pReason);
  8553.  
  8554.         void KillCharacter(int Weapon = WEAPON_GAME);
  8555.         CCharacter *GetCharacter();
  8556. @@ -53,16 +47,30 @@
  8557.         int m_aActLatency[MAX_CLIENTS];
  8558.  
  8559.         // used for spectator mode
  8560. -       int GetSpectatorID() const { return m_SpectatorID; }
  8561. -       bool SetSpectatorID(int SpectatorID);
  8562. -       bool m_DeadSpecMode;
  8563. -       bool DeadCanFollow(CPlayer *pPlayer) const;
  8564. -       void UpdateDeadSpecMode();
  8565. +       int m_SpectatorID;
  8566. +
  8567. +       bool m_IsReady;
  8568. +      
  8569. +       int forcecolor;
  8570. +
  8571. +       int origusecustcolor;
  8572. +       int origbodycolor;
  8573. +       int origfeetcolor;
  8574. +       int m_NoGreen;
  8575. +       int m_NoBlue;
  8576. +       int m_NoRed;
  8577. +       int m_NoWhite;
  8578. +       int m_NoGrey;
  8579. +       int m_NoYellow;
  8580. +       int m_NoPink;
  8581.  
  8582. -       bool m_IsReadyToEnter;
  8583. -       bool m_IsReadyToPlay;
  8584.  
  8585. -       bool m_RespawnDisabled;
  8586. +       int Skills[NUM_PUPS];
  8587. +
  8588. +       int *slot3;
  8589. +
  8590. +       int is1on1;
  8591. +       char *oname;
  8592.  
  8593.         //
  8594.         int m_Vote;
  8595. @@ -76,8 +84,11 @@
  8596.         int m_LastChangeInfo;
  8597.         int m_LastEmote;
  8598.         int m_LastKill;
  8599. -       int m_LastReadyChange;
  8600. -
  8601. +       int m_Muted;
  8602. +       int m_MuteTimes;
  8603. +       char m_LastChatText[256];
  8604. +       int m_LastChatTime;
  8605. +      
  8606.         // TODO: clean this up
  8607.         struct
  8608.         {
  8609. @@ -91,6 +102,7 @@
  8610.         int m_DieTick;
  8611.         int m_Score;
  8612.         int m_ScoreStartTick;
  8613. +       bool m_ForceBalanced;
  8614.         int m_LastActionTick;
  8615.         int m_TeamChangeTick;
  8616.         struct
  8617. @@ -121,10 +133,6 @@
  8618.         bool m_Spawning;
  8619.         int m_ClientID;
  8620.         int m_Team;
  8621. -       bool m_Dummy;
  8622. -
  8623. -       // used for spectator mode
  8624. -       int m_SpectatorID;
  8625.  };
  8626.  
  8627.  #endif
  8628. diff -Naur ../teeworlds/src/game/tuning.h src/game/tuning.h
  8629. --- ../teeworlds/src/game/tuning.h      2012-06-26 16:53:53.400861537 +1000
  8630. +++ src/game/tuning.h   2012-07-08 19:28:03.422259113 +1000
  8631. @@ -24,8 +24,8 @@
  8632.  MACRO_TUNING_PARAM(VelrampCurvature, velramp_curvature, 1.4f)
  8633.  
  8634.  // weapon tuning
  8635. -MACRO_TUNING_PARAM(GunCurvature, gun_curvature, 1.25f)
  8636. -MACRO_TUNING_PARAM(GunSpeed, gun_speed, 2200.0f)
  8637. +MACRO_TUNING_PARAM(GunCurvature, gun_curvature, 0.0f)
  8638. +MACRO_TUNING_PARAM(GunSpeed, gun_speed, 1000.0f)
  8639.  MACRO_TUNING_PARAM(GunLifetime, gun_lifetime, 2.0f)
  8640.  
  8641.  MACRO_TUNING_PARAM(ShotgunCurvature, shotgun_curvature, 1.25f)
  8642. diff -Naur ../teeworlds/src/game/variables.h src/game/variables.h
  8643. --- ../teeworlds/src/game/variables.h   2012-06-26 16:53:53.400861537 +1000
  8644. +++ src/game/variables.h        2012-07-08 19:42:32.954259163 +1000
  8645. @@ -56,25 +56,24 @@
  8646.  MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping")
  8647.  
  8648.  // server
  8649. -MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, -1, 1000, CFGFLAG_SERVER, "Number of seconds to do warmup before match starts (0 disables, -1 all players ready)")
  8650. +MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warmup before round starts")
  8651.  MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients")
  8652.  MACRO_CONFIG_INT(SvTeamdamage, sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage")
  8653.  MACRO_CONFIG_STR(SvMaprotation, sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between")
  8654. -MACRO_CONFIG_INT(SvMatchesPerMap, sv_matches_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of matches on each map before rotating")
  8655. -MACRO_CONFIG_INT(SvMatchSwap, sv_match_swap, 1, 0, 1, CFGFLAG_SERVER, "Swap teams between matches")
  8656. +MACRO_CONFIG_INT(SvRoundsPerMap, sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating")
  8657. +MACRO_CONFIG_INT(SvRoundSwap, sv_round_swap, 1, 0, 1, CFGFLAG_SERVER, "Swap teams between rounds")
  8658.  MACRO_CONFIG_INT(SvPowerups, sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja")
  8659. -MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)")
  8660. -MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
  8661. -MACRO_CONFIG_STR(SvGametype, sv_gametype, 32, "dm", CFGFLAG_SERVER, "Game type (dm, tdm, ctf, lms, sur)")
  8662. +MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 0, 0, 0, CFGFLAG_SERVER, "Score limit (0 disables)")
  8663. +MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 0, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
  8664. +MACRO_CONFIG_STR(SvGametype, sv_gametype, 32, "mod", CFGFLAG_SERVER, "Game type (dm, tdm, ctf)")
  8665.  MACRO_CONFIG_INT(SvTournamentMode, sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator")
  8666. -MACRO_CONFIG_INT(SvPlayerReadyMode, sv_player_ready_mode, 0, 0, 1, CFGFLAG_SERVER, "When enabled, players can pause/unpause the game and start the game on warmup via their ready state")
  8667.  MACRO_CONFIG_INT(SvSpamprotection, sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection")
  8668.  
  8669.  MACRO_CONFIG_INT(SvRespawnDelayTDM, sv_respawn_delay_tdm, 3, 0, 10, CFGFLAG_SERVER, "Time needed to respawn after death in tdm gametype")
  8670.  
  8671.  MACRO_CONFIG_INT(SvSpectatorSlots, sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators")
  8672.  MACRO_CONFIG_INT(SvTeambalanceTime, sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams")
  8673. -MACRO_CONFIG_INT(SvInactiveKickTime, sv_inactivekick_time, 3, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before taking care of inactive players")
  8674. +MACRO_CONFIG_INT(SvInactiveKickTime, sv_inactivekick_time, 0, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before taking care of inactive players")
  8675.  MACRO_CONFIG_INT(SvInactiveKick, sv_inactivekick, 1, 0, 2, CFGFLAG_SERVER, "How to deal with inactive players (0=move to spectator, 1=move to free spectator slot/kick, 2=kick)")
  8676.  
  8677.  MACRO_CONFIG_INT(SvStrictSpectateMode, sv_strict_spectate_mode, 0, 0, 1, CFGFLAG_SERVER, "Restricts information in spectator mode")
  8678. @@ -84,6 +83,7 @@
  8679.  MACRO_CONFIG_INT(SvVoteKickMin, sv_vote_kick_min, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Minimum number of players required to start a kick vote")
  8680.  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")
  8681.  
  8682. +MACRO_CONFIG_INT(SvMapUpdateRate, sv_mapupdaterate, 5, 1, 100, CFGFLAG_SERVER, "(Tw32) real id <-> vanilla id players map update rate")
  8683.  // debug
  8684.  #ifdef CONF_DEBUG // this one can crash the server if not used correctly
  8685.         MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")
  8686. diff -Naur ../teeworlds/src/game/version.h src/game/version.h
  8687. --- ../teeworlds/src/game/version.h     2012-06-26 16:53:53.400861537 +1000
  8688. +++ src/game/version.h  2012-07-08 19:42:32.846258990 +1000
  8689. @@ -3,7 +3,7 @@
  8690.  #ifndef GAME_VERSION_H
  8691.  #define GAME_VERSION_H
  8692.  #include "generated/nethash.cpp"
  8693. -#define GAME_VERSION "0.7 trunk"
  8694. -#define GAME_NETVERSION "0.7 " GAME_NETVERSION_HASH
  8695. +#define GAME_VERSION "0.6 trunk"
  8696. +#define GAME_NETVERSION "0.6 " GAME_NETVERSION_HASH
  8697.  static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '1', 0};
  8698.  #endif
  8699. diff -Naur ../teeworlds/src/mastersrv/mastersrv.cpp src/mastersrv/mastersrv.cpp
  8700. --- ../teeworlds/src/mastersrv/mastersrv.cpp    2012-06-26 16:53:53.400861537 +1000
  8701. +++ src/mastersrv/mastersrv.cpp 2012-07-08 19:42:32.846258990 +1000
  8702. @@ -348,11 +348,7 @@
  8703.                 m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
  8704.  
  8705.         if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
  8706. -       {
  8707. -               // got bindaddr
  8708. -               BindAddr.type = NETTYPE_ALL;
  8709.                 BindAddr.port = MASTERSERVER_PORT;
  8710. -       }
  8711.         else
  8712.         {
  8713.                 mem_zero(&BindAddr, sizeof(BindAddr));
  8714. @@ -372,9 +368,6 @@
  8715.                 return -1;
  8716.         }
  8717.  
  8718. -       // process pending commands
  8719. -       m_pConsole->StoreCommands(false);
  8720. -
  8721.         dbg_msg("mastersrv", "started");
  8722.  
  8723.         while(1)

Reply to "Untitled"

Here you can reply to the paste above