Conflicts:
	src/engine/shared/console.cpp
	src/game/client/components/hud.cpp
	src/game/client/components/scoreboard.cpp
	src/game/server/entities/character.cpp
	src/game/server/entities/projectile.cpp
This commit is contained in:
GreYFoXGTi 2011-01-12 11:08:17 +02:00
commit 2ec0e0eec4
35 changed files with 1336 additions and 206 deletions

3
.gitignore vendored
View file

@ -1,9 +1,12 @@
bam
.bam .bam
config.lua config.lua
datasrc/__pycache__ datasrc/__pycache__
datasrc/*.pyc datasrc/*.pyc
objs objs
src/game/generated src/game/generated
SDL.dll
autoexec.cfg
crapnet* crapnet*
dilate* dilate*

View file

@ -894,6 +894,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -891,6 +891,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -963,6 +963,9 @@ no limit
Name plates size Name plates size
== ==
Unable to delete the demo
==
##### old translations ##### ##### old translations #####
##### DDRace ##### ##### DDRace #####

View file

@ -894,6 +894,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -286,9 +286,6 @@ Grenade
Group Group
== Groupe == Groupe
HD
== HD
Hammer Hammer
== Maillet == Maillet
@ -924,6 +921,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Use Clipping Use Clipping
== ==

View file

@ -963,6 +963,9 @@ no limit
Name plates size Name plates size
== ==
Unable to delete the demo
==
##### old translations ##### ##### old translations #####
##### DDRace ##### ##### DDRace #####

View file

@ -28,6 +28,9 @@ polish
portuguese portuguese
== Português == Português
romanian
== Română
russian russian
== Русский == Русский

View file

@ -888,6 +888,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -939,6 +939,9 @@ Tiles
Time limit: %d min Time limit: %d min
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -894,6 +894,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

970
data/languages/romanian.txt Normal file
View file

@ -0,0 +1,970 @@
##### translated strings #####
%d of %d servers, %d players
== %d/%d servere, %d jucători
%d%% loaded
== %d%% încărcat
%ds left
== %ds a ieșit
%i minute left
== %i minute rămas
%i minutes left
== %i minutes rămase
%i second left
== %i secundă rămasă
%i seconds left
== %i secunde rămase
%s Right click for context menu.
== %s Clic dreapta pentru meniul contextual.
Abort
== Anulează
Add
== Adaugă
Add Image
== Adaugă o imagine
Add Quad
== Adaugă quad
Add group
== Adaugă un grup
Add quads layer
== Adaugă strat quad-uri
Add tile layer
== Adaugă strat cu plăci
Address
== Adresa
Adds a new group
== Adaugă un grup nou
Adds a new quad
== Adaugă un nou quad
All
== Toți
Alpha
== Alfa
Alpha value of the envelope
== Valoarea alfa a plicului
Always show name plates
== Afișează întotdeauna pseudonimele
Anim
== Anim.
Append
== Adaugă
Append map
== Adaugă unei hărți
Are you sure that you want to delete the demo?
== Sigur vrei să ștergi demo-ul?
Are you sure that you want to quit?
== Sigur vrei să ieși?
As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.
== Aceasta fiind prima lansare a jocului, te rog introdu-ți pseudonimul mai jos. E recomandat să verifici setările și să le ajustezi cum vrei înainte să intri pe un server.
Aspect ratio
== Rația de aspect
Automatically record demos
== Înregistrează automat demo-uri
Automatically take game over screenshot
== Fă automat o captură de ecran la final
Blue team
== Echipa albastră
Blue team wins!
== Echipa albastră a câștigat!
Blue value of the envelope
== Valoarea albastră a plicului
Body
== Corp
Border
== Bordură
CCW
== ST
CW
== DR
Call vote
== Votează
Cancel
== Anulează
Chat
== Chat
Clear collision
== Curăță coliziunea
Clip H
== Î clip
Clip W
== L clip
Clip X
== X clip
Clip Y
== Y clip
Close
== Închide
Color
== Culoare
Color Env
== Culoare Env
Color TO
== Culoare TO
Color+
== Culoare+
Compatible version
== Versiune compatibilă
Connect
== Conectează
Connecting to
== Conectare la
Connection Problems...
== Probleme la conexiune...
Console
== Consolă
Constructs collision from this layer
== Construiește coliziunea din acest strat
Controls
== Controale
Creates a new color envelope
== Creează un plic într-o culoare nouă
Creates a new map
== Creează o hartă nouă
Creates a new pos envelope
== Creează un nou plic poz
Creates a new quad layer
== Creează un nou strat quad
Creates a new tile layer
== Creează un nou strat de plăci
Current
== Curent
Current version: %s
== Versiunea actuală : %s
Custom colors
== Culori personalizate
Decrease
== Redu
Decrease animation speed
== Redu viteza animațiilor
Delete
== Șterge
Delete demo
== Șterge demonstrația
Delete group
== Șterge grupul
Delete layer
== Șterge stratul
Delete this envelope
== Șterge acest plic
Deletes the current quad
== Șterge acest quad
Deletes the layer
== Șterge stratul
Demos
== Demo
Detail
== Detalii
Disconnect
== Deconectare
Disconnected
== Deconectat
Display Modes
== Moduri de afișare
Down
== Jos
Downloading map
== Se descarcă harta
Draw!
== Egalitate!
Dynamic Camera
== Cameră dinamică
Embed
== Integrează
Embedded
== Integrat
Embeds the image into the map file.
== Integrează imaginea în fișierul hărții.
Emoticon
== Figurine
Enable/disable group for saving
== Comută salvarea grupului
Enable/disable layer for saving
== Comută salvarea stratului
Enter
== Intră
Envelopes
== Plicuri
Error
== Eroare
Error loading demo
== Eroare la încărcarea demo-ului
Exit
== Ieșire
Exits from the editor
== Închide editorul
External
== Extern
FSAA samples
== Eșantioane FSAA
Favorite
== Favorit
Favorites
== Favorite
Feet
== Picioare
File
== Fișier
File: %s
== Fișier : %s
Filename:
== Numele fișierului:
Filter
== Filtre
Fire
== Foc
Folder
== Dosar
Force vote
== Forțează votul
Fullscreen
== Ecrat complet
Game
== Joc
Game info
== Informații joc
Game over
== Final de joc
Game type
== Tip de joc
Game types:
== Tipuri de joc:
General
== General
Graphics
== Grafică
Green value of the envelope
== Valoarea verde a plicului
Grenade
== Grenade
Group
== Grup
HD
== HD
Hammer
== Ciocan
Has people playing
== Are jucători activi
Height
== Înălțime
High Detail
== Detalii înalte
Hook
== Cârlig
Host address
== Adresa gazdei
Hue
== Tentă
Image
== Imagine
Images
== Imagini
Increase
== Mărește
Increase animation speed
== Mărește viteza animației
Info
== Informații
Internet
== Internet
Invalid Demo
== Demo nevalid
Join blue
== La albaștri
Join game
== Intră în joc
Join red
== La roșii
Jump
== Salt
Kick
== Dă afară
LAN
== LAN
Language
== Limba
Layers
== Straturi
Left
== Stânga
Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate.
== Clic stânga pentru mutare. Ține Shift pentru mutare pibot. Ține Ctrl pentru rotire.
Left mouse button to move. Hold shift to move the texture.
== Clic stânga pentru mutare. Ține Shift pentru mutarea texturii.
Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete.
== Clic stânga pentru tragere. Ține Ctrl pentru precizie. Ține Shift pentru modificarea timpului. Clic dreapta pentru ștergere.
Lht.
== Lum.
Load
== Încarcă
Load a new image to use in the map
== Încarcă o imagine pentru utilizarea pe hartă
Load map
== Încarcă o hartă
Loading
== Se încarcă
MOTD
== Mesajul zilei
Make collision
== Creează coliziunea
Make external
== Fă-o externă
Map
== Hartă
Max Screenshots
== Număr maxim de capturi de ecran
Max demos
== Număr maxim de demo-uri
Maximum ping:
== Ping maxim:
Miscellaneous
== Diverse
Mouse sens.
== Sensib. maus
Move left
== Mută la stânga
Move right
== Mută la dreapta
Movement
== Mișcare
Mute when not active
== Mută la inactivate
Name
== Nume
Name plates size
== Dimensiune nume placă
Name:
== Nume:
New
== Nou
New folder
== Dosar nou
News
== Știri
Next Envelope
== Plicul următor
Next weapon
== Arma următoare
Nickname
== Pseudonim
No
== Nu
No password
== Fără parolă
No servers found
== Nici un server găsit
No servers match your filter criteria
== Nici un server nu corespunde criteriilor
None
== Niciunul
Normal animation speed
== Viteza normală a animațiilor
Ok
== Bine
Open
== Deschide
Opens a map and adds everything from that map to the current one
== Deschide o hartă și adaugă totul de pe ea pe cea curentă
Opens a map for editing
== Deschide o hartă pentru editare
Order
== Ordine
Para X
== Para X
Para Y
== Para Y
Parent Folder
== Dosarul părinte
Password
== Parolă
Password incorrect
== Parolă incorectă
Ping
== Ping
Pistol
== Pistol
Play
== Joacă
Player
== Jucător
Players
== Jucători
Please balance teams!
== Echilibrați echipele!
Pos X
== Poz X
Pos Y
== Poz Y
Pos. Env
== Poz Env
Pos. TO
== Poz TO
Pos.+
== Pos.+
Press right mouse button to create a new point
== Clic-dreapta pentru crearea unui punct nou
Prev. weapon
== Arma precedentă
Previous Envelope
== Plicul anterior
Proof
== Negativ
Quads
== Quad-uri
Quality Textures
== Texturi de înaltă calitate
Quick search:
== Căutare rapidă:
Quit
== Ieșire
REC
== REC
Reason:
== Motiv:
Record demo
== Înreg. demo
Red team
== Echipa roșie
Red team wins!
== Echipa roșie a câștigat!
Red value of the envelope
== Valoarea roșie a plicului
Refocus
== Refocus
Refresh
== Reîncarcă
Refreshing master servers
== Reîncarcă serverele principale
Remote console
== Consolă server
Remove
== Elimină
Removes collision from this layer
== Elimină coliziunea din acest strat
Removes the image from the map
== Elimină imaginea din hartă
Removes the image from the map file.
== Elimină imaginea din fișierul hărții.
Replace
== Înlocuiește
Replace Image
== Înlocuiește imaginea
Replaces the image with a new one
== Înlocuiește imaginea cu una nouă
Reset filter
== Filtru implicit
Reset to defaults
== Setări implicite
Resizes the current Quad based on the aspect ratio of the image
== Redimensionează quad-ul curent în baza rației de aspect a imaginii
Rifle
== Mitralieră
Right
== Dreapta
Rotation of the brush in degrees. Use left mouse button to drag and change the value. Hold shift to be more precise.
== Rotația pensulei în grade. Folosește butonul stânga al mausului pentru a trage și modifica valoarea. Ține Shift pentru precizie.
Rotation of the envelope
== Rotirea plicului
Round
== Runda
Sample rate
== Frecvența
Sat.
== Sat.
Save
== Salvează
Save As
== Salvează ca
Save map
== Salvează harta
Saves the current map
== Salvează harta curentă
Saves the current map under a new name
== Salvează harta curentă sub un nume nou
Score
== Scor
Score board
== Scoruri
Score limit
== Limita de scor
Scoreboard
== Scoruri
Screenshot
== Captură de ecran
Select group. Right click for properties.
== Alege un grup. Clic-dreapta pentru proprietăți.
Select image
== Alege o imagine
Select layer. Right click for properties.
== Alege un strat. Clic-dreapta pentru prorpietăți.
Server details
== Detalii server
Server info
== Info. server
Server not full
== Are locuri libere
Settings
== Setări
Shift
== Shift
Shotgun
== Pușcă
Show chat
== Afișare chat
Show name plates
== Arată pseudonimele
Show only supported
== Arată doar modurile suportate
Skins
== Costume
Sound
== Sunet
Sound volume
== Volum sunet
Spectate
== Spectator
Spectators
== Spectatori
Square
== Pătrat
Squares the current quad
== Fă pătrat quad-ul curent
Standard gametype
== Jocuri standard
Standard map
== Hărți standard
Stop record
== Stop înreg.
Sudden Death
== Moarte subită
Switch between images and layers managment.
== Comută între gestiune imagini și straturi.
Switch curve type
== Comută tipul de curbă
Switch weapon on pickup
== Schimbă arma la găsire
Team
== Echipa
Team chat
== Chat cu echipa
Teeworlds %s is out! Download it at www.teeworlds.com!
== Teeworlds %s este lansat! Descarcă-l de la www.teeworlds.com!
Texture Compression
== Compresie texturi
The server is running a non-standard tuning on a pure game type.
== Serverul folosește parametri ne-standard într-un joc standard.
Tiles
== Plăci
Time limit
== Timp limită
Time limit: %d min
== Timp limită : %d min
Toggle group visibility
== Comută vizibilitatea grupului
Toggle layer visibility
== Comută vizibilitatea stratului
Toggles the envelope editor.
== Comută editorul de plicuri.
Try again
== Reîncearcă
Type
== Tip
UI Color
== Culoare meniu
Up
== Sus
Use Clipping
== Folosește decuparea
Use left mouse button to drag and change the color value. Hold shift to be more precise.
== Folosește butonul stâng al mausului pentru a trage și schimba valoarea culorii. Ține Shift pentru precizie.
Use left mouse button to drag and change the value. Hold shift to be more precise.
== Folosește butonul stâng al mausului pentru a trage și schimba valoarea. Ține Shift pentru precizie.
Use left mouse button to drag and create a brush.
== Folosește butonul stâng al mausului pentru a trage și crea o pensulă.
Use left mouse button to paint with the brush. Right button clears the brush.
== Folosește butonul stâng al mausului pentru a picta cu pensula. Clic dreapta curăță pensula.
Use sounds
== Folosește sunetul
V-Sync
== Sincronizare verticală (V-Sync)
Version
== Versiune
Vote no
== Votează nu
Vote yes
== Votează da
Voting
== Votare
Warmup
== Încălzire
Weapon
== Arme
Welcome to Teeworlds
== Bun venit în Teeworlds
Width
== Lățime
X-axis of the envelope
== Axa-X a plicului
Y-axis of the envelope
== Axa-Y a plicului
Yes
== Da
You must restart the game for all settings to take effect.
== Trebuie să repornești jocul pentru aplicarea setărilor.
Your skin
== Costumul tău
ZI
== MA
ZO
== MI
[HOME] Restore map focus
== [HOME] Restaurează focusul hărții
[M] Flip brush vertical
== [M] Întoarce pe verticală
[N] Flip brush horizontal
== [N] Întoarce pe orizontală
[NumPad*] Zoom to normal and remove editor offset
== [NumPad*] Focalizare normală și eliminare deplasament editor
[NumPad+] Zoom in
== [Numeric+] Mărire
[NumPad-] Zoom out
== [Numeric-] Micșorare
[R] Rotates the brush counter clockwise
== [R] Rotește peria spre stânga
[T] Rotates the brush clockwise
== [T] Rotește peria spre dreapta
[ctrl+h] Toggle High Detail
== [Ctrl+H] Comută detaliile înalte
[ctrl+m] Toggle animation
== [Ctrl+M] Comută animația
[ctrl+p] Toggles proof borders. These borders represent what a player maximum can see.
== [Ctrl+P] Comută bordurile negativului. Aceste borduri reprezintă maximul vizibil jucătorilor.
no limit
== fără limită
##### needs translation #####
Unable to delete the demo
==
##### old translations #####

View file

@ -939,6 +939,9 @@ Tiles
Time limit: %d min Time limit: %d min
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -894,6 +894,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -888,6 +888,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -945,6 +945,9 @@ Rotation of the envelope
Shift Shift
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -8,8 +8,8 @@ source_exts = [".c", ".cpp", ".h"]
def parse_source(): def parse_source():
stringtable = {} stringtable = {}
def process_line(line): def process_line(line):
if 'Localize("' in line: if b'Localize("' in line:
fields = line.split('Localize("', 1)[1].split('"', 1) fields = line.split(b'Localize("', 1)[1].split(b'"', 1)
stringtable[fields[0]] = "" stringtable[fields[0]] = ""
process_line(fields[1]) process_line(fields[1])
@ -34,9 +34,9 @@ def load_languagefile(filename):
stringtable = {} stringtable = {}
for i in range(0, len(lines)-1): for i in range(0, len(lines)-1):
l = lines[i].decode("utf-8").strip() l = lines[i].strip()
if len(l) and not l[0] == '=' and not l[0] == '#': if len(l) and not l[0:1] == b"=" and not l[0:1] == b"#":
stringtable[l] = lines[i+1][3:].decode("utf-8").rstrip() stringtable[l] = lines[i+1][3:].rstrip()
return stringtable return stringtable
@ -52,28 +52,27 @@ def generate_languagefile(outputfilename, srctable, loctable):
srctable_keys.append(key) srctable_keys.append(key)
srctable_keys.sort() srctable_keys.sort()
content = "\n##### translated strings #####\n\n" content = b"\n##### translated strings #####\n\n"
for k in srctable_keys: for k in srctable_keys:
if k in loctable and len(loctable[k]): if k in loctable and len(loctable[k]):
content += "%s\n== %s\n\n" % (k, loctable[k]) content += k + b"\n== " + loctable[k] + b"\n\n"
num_items += 1 num_items += 1
content += b"##### needs translation #####\n\n"
content += "##### needs translation #####\n\n"
for k in srctable_keys: for k in srctable_keys:
if not k in loctable or len(loctable[k]) == 0: if not k in loctable or len(loctable[k]) == 0:
content += "%s\n== \n\n" % (k) content += k + b"\n== \n\n"
num_items += 1 num_items += 1
new_items += 1 new_items += 1
content += "##### old translations #####\n\n" content += b"##### old translations #####\n\n"
for k in loctable: for k in loctable:
if not k in srctable: if not k in srctable:
content += "%s\n== %s\n\n" % (k, loctable[k]) content += k + b"\n== " + loctable[k] + b"\n\n"
num_items += 1 num_items += 1
old_items += 1 old_items += 1
f.write(content.encode("utf-8")) f.write(content)
f.close() f.close()
print("%-40s %8d %8d %8d" % (outputfilename, num_items, new_items, old_items)) print("%-40s %8d %8d %8d" % (outputfilename, num_items, new_items, old_items))

View file

@ -77,6 +77,7 @@ public:
virtual void Quit() = 0; virtual void Quit() = 0;
virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0; virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0;
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp) = 0; virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;
virtual void DemoRecorder_Stop() = 0; virtual void DemoRecorder_Stop() = 0;
virtual void AutoScreenshot_Start() = 0; virtual void AutoScreenshot_Start() = 0;

View file

@ -2159,6 +2159,7 @@ void CClient::DemoRecorder_HandleAutoStart()
{ {
if(g_Config.m_ClAutoDemoRecord) if(g_Config.m_ClAutoDemoRecord)
{ {
DemoRecorder_Stop();
DemoRecorder_Start("auto/autorecord", true); DemoRecorder_Start("auto/autorecord", true);
if(g_Config.m_ClAutoDemoMax) if(g_Config.m_ClAutoDemoMax)
{ {

View file

@ -688,21 +688,20 @@ public:
if(pChr) if(pChr)
{ {
Advance = pChr->m_AdvanceX + Kerning(pFont, Character, Nextcharacter)*Scale;
if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+Advance*Size-pCursor->m_StartX > pCursor->m_LineWidth)
{
// we hit the end of the line, no more to render or count
pCurrent = pEnd;
break;
}
if(pCursor->m_Flags&TEXTFLAG_RENDER) if(pCursor->m_Flags&TEXTFLAG_RENDER)
{ {
Graphics()->QuadsSetSubset(pChr->m_aUvs[0], pChr->m_aUvs[1], pChr->m_aUvs[2], pChr->m_aUvs[3]); Graphics()->QuadsSetSubset(pChr->m_aUvs[0], pChr->m_aUvs[1], pChr->m_aUvs[2], pChr->m_aUvs[3]);
IGraphics::CQuadItem QuadItem(DrawX+pChr->m_OffsetX*Size, DrawY+pChr->m_OffsetY*Size, pChr->m_Width*Size, pChr->m_Height*Size); IGraphics::CQuadItem QuadItem(DrawX+pChr->m_OffsetX*Size, DrawY+pChr->m_OffsetY*Size, pChr->m_Width*Size, pChr->m_Height*Size);
Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsDrawTL(&QuadItem, 1);
} }
Advance = pChr->m_AdvanceX + Kerning(pFont, Character, Nextcharacter)*Scale;
}
if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+(Advance+pChr->m_Width)*Size-pCursor->m_StartX > pCursor->m_LineWidth)
{
// we hit the end of the line, no more to render or count
pCurrent = pEnd;
break;
} }
DrawX += Advance*Size; DrawX += Advance*Size;

View file

@ -264,7 +264,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
{ {
while(pStr && *pStr) while(pStr && *pStr)
{ {
CResult *pResult = new(&m_ExecutionQueue.m_pLast->m_Result) CResult; CResult Result;
const char *pEnd = pStr; const char *pEnd = pStr;
const char *pNextPart = 0; const char *pNextPart = 0;
int InString = 0; int InString = 0;
@ -292,24 +292,24 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
pEnd++; pEnd++;
} }
if(ParseStart(pResult, pStr, (pEnd-pStr) + 1) != 0) if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0)
return; return;
CCommand *pCommand = FindCommand(pResult->m_pCommand, m_FlagMask); CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask);
if(pCommand) if(pCommand)
{ {
int IsStrokeCommand = 0; int IsStrokeCommand = 0;
if(pResult->m_pCommand[0] == '+') if(Result.m_pCommand[0] == '+')
{ {
// insert the stroke direction token // insert the stroke direction token
pResult->AddArgument(m_paStrokeStr[Stroke]); Result.AddArgument(m_paStrokeStr[Stroke]);
IsStrokeCommand = 1; IsStrokeCommand = 1;
} }
if(Stroke || IsStrokeCommand) if(Stroke || IsStrokeCommand)
{ {
if(ParseArgs(pResult, pCommand->m_pParams)) if(ParseArgs(&Result, pCommand->m_pParams))
{ {
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
char aBuf[256]; char aBuf[256];
@ -319,14 +319,15 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
} }
else if(m_StoreCommands && pCommand->m_Flags&CFGFLAG_STORE) else if(m_StoreCommands && pCommand->m_Flags&CFGFLAG_STORE)
{ {
m_ExecutionQueue.AddEntry();
m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback; m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback;
m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData; m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData;
m_ExecutionQueue.AddEntry(); m_ExecutionQueue.m_pLast->m_Result = Result;
} }
else else
{ {
if(pResult->GetVictim() == CResult::VICTIM_ME) if(Result.GetVictim() == CResult::VICTIM_ME)
pResult->SetVictim(ClientId); Result.SetVictim(ClientId);
if((ClientLevel < pCommand->m_Level && !(pCommand->m_Flags & CMDFLAG_HELPERCMD)) || (ClientLevel < 1 && (pCommand->m_Flags & CMDFLAG_HELPERCMD))) if((ClientLevel < pCommand->m_Level && !(pCommand->m_Flags & CMDFLAG_HELPERCMD)) || (ClientLevel < 1 && (pCommand->m_Flags & CMDFLAG_HELPERCMD)))
{ {
@ -346,7 +347,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
} }
else if(ClientLevel == 1 && (pCommand->m_Flags & CMDFLAG_HELPERCMD) && pResult->GetVictim() != ClientId) else if(ClientLevel == 1 && (pCommand->m_Flags & CMDFLAG_HELPERCMD) && Result.GetVictim() != ClientId)
{ {
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "As a helper you can't use commands on others."); PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "As a helper you can't use commands on others.");
@ -369,19 +370,19 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
} }
else else
{ {
if (pResult->HasVictim()) if (Result.HasVictim())
{ {
if(pResult->GetVictim() == CResult::VICTIM_ALL) if(Result.GetVictim() == CResult::VICTIM_ALL)
{ {
for (int i = 0; i < MAX_CLIENTS; i++) for (int i = 0; i < MAX_CLIENTS; i++)
{ {
if (ClientOnline(i) && CompareClients(ClientLevel, i)) if (ClientOnline(i) && CompareClients(ClientLevel, i))
{ {
pResult->SetVictim(i); Result.SetVictim(i);
RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData); RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData);
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId);
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
ReleaseAlternativePrintCallback(); ReleaseAlternativePrintCallback();
@ -390,13 +391,13 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
} }
else else
{ {
if (!ClientOnline(pResult->GetVictim())) if (!ClientOnline(Result.GetVictim()))
{ {
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "client is offline"); PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "client is offline");
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
} }
else if (!CompareClients(ClientLevel, pResult->GetVictim()) && ClientId != pResult->GetVictim()) else if (!CompareClients(ClientLevel, Result.GetVictim()) && ClientId != Result.GetVictim())
{ {
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "you can not use commands on players with the same or higher level than you"); PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "you can not use commands on players with the same or higher level than you");
@ -407,7 +408,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData); RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData);
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId);
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
ReleaseAlternativePrintCallback(); ReleaseAlternativePrintCallback();
@ -419,7 +420,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData); RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData);
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId);
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
ReleaseAlternativePrintCallback(); ReleaseAlternativePrintCallback();
@ -433,7 +434,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client
RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData);
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "No such command: %s.", pResult->m_pCommand); str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", aBuf); PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", aBuf);
ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintResponseCallback();
@ -762,7 +763,7 @@ void CConsole::StoreCommands(bool Store, int ClientId)
{ {
if(!Store) if(!Store)
{ {
for(CExecutionQueue::CQueueEntry *pEntry = m_ExecutionQueue.m_pFirst; pEntry != m_ExecutionQueue.m_pLast; pEntry = pEntry->m_pNext) for(CExecutionQueue::CQueueEntry *pEntry = m_ExecutionQueue.m_pFirst; pEntry; pEntry = pEntry->m_pNext)
pEntry->m_pfnCommandCallback(&pEntry->m_Result, pEntry->m_pCommandUserData, ClientId); pEntry->m_pfnCommandCallback(&pEntry->m_Result, pEntry->m_pCommandUserData, ClientId);
m_ExecutionQueue.Reset(); m_ExecutionQueue.Reset();
} }

View file

@ -6,6 +6,9 @@
#include <engine/console.h> #include <engine/console.h>
#include "memheap.h" #include "memheap.h"
#include <new>
class CConsole : public IConsole class CConsole : public IConsole
{ {
class CCommand : public CCommandInfo class CCommand : public CCommandInfo
@ -82,6 +85,29 @@ class CConsole : public IConsole
const char *m_pCommand; const char *m_pCommand;
const char *m_apArgs[MAX_PARTS]; const char *m_apArgs[MAX_PARTS];
CResult() : IResult()
{
mem_zero(m_aStringStorage, sizeof(m_aStringStorage));
m_pArgsStart = 0;
m_pCommand = 0;
mem_zero(m_apArgs, sizeof(m_apArgs));
}
CResult &operator =(const CResult &Other)
{
if(this != &Other)
{
IResult::operator=(Other);
int Offset = m_aStringStorage - Other.m_aStringStorage;
mem_copy(m_aStringStorage, Other.m_aStringStorage, sizeof(m_aStringStorage));
m_pArgsStart = Other.m_pArgsStart + Offset;
m_pCommand = Other.m_pCommand + Offset;
for(unsigned i = 0; i < Other.m_NumArgs; ++i)
m_apArgs[i] = Other.m_apArgs[i] + Offset;
}
return *this;
}
enum enum
{ {
VICTIM_NONE=-3, VICTIM_NONE=-3,
@ -127,14 +153,17 @@ class CConsole : public IConsole
{ {
CQueueEntry *pEntry = static_cast<CQueueEntry *>(m_Queue.Allocate(sizeof(CQueueEntry))); CQueueEntry *pEntry = static_cast<CQueueEntry *>(m_Queue.Allocate(sizeof(CQueueEntry)));
pEntry->m_pNext = 0; pEntry->m_pNext = 0;
m_pLast->m_pNext = pEntry; if(!m_pFirst)
m_pFirst = pEntry;
if(m_pLast)
m_pLast->m_pNext = pEntry;
m_pLast = pEntry; m_pLast = pEntry;
(void)new(&(pEntry->m_Result)) CResult;
} }
void Reset() void Reset()
{ {
m_Queue.Reset(); m_Queue.Reset();
m_pFirst = m_pLast = static_cast<CQueueEntry *>(m_Queue.Allocate(sizeof(CQueueEntry))); m_pFirst = m_pLast = 0;
m_pLast->m_pNext = 0;
} }
} m_ExecutionQueue; } m_ExecutionQueue;

View file

@ -8,6 +8,8 @@
#include <game/client/gameclient.h> #include <game/client/gameclient.h>
#include <game/client/components/scoreboard.h>
#include "broadcast.h" #include "broadcast.h"
void CBroadcast::OnReset() void CBroadcast::OnReset()
@ -17,13 +19,16 @@ void CBroadcast::OnReset()
void CBroadcast::OnRender() void CBroadcast::OnRender()
{ {
if(m_pClient->m_pScoreboard->Active())
return;
Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300);
if(time_get() < m_BroadcastTime) if(time_get() < m_BroadcastTime)
{ {
CTextCursor Cursor; CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = 300*Graphics()->ScreenAspect()-2*m_BroadcastRenderOffset; Cursor.m_LineWidth = 300*Graphics()->ScreenAspect()-m_BroadcastRenderOffset;
TextRender()->TextEx(&Cursor, m_aBroadcastText, -1); TextRender()->TextEx(&Cursor, m_aBroadcastText, -1);
} }
} }

View file

@ -62,7 +62,14 @@ void CHud::RenderGameTimer()
str_format(Buf, sizeof(Buf), "%02d:%02d.%d", Time/60, Time%60, m_DDRaceTick/10); str_format(Buf, sizeof(Buf), "%02d:%02d.%d", Time/60, Time%60, m_DDRaceTick/10);
float FontSize = 10.0f; float FontSize = 10.0f;
float w = TextRender()->TextWidth(0, 12,"00:00.0",-1); float w = TextRender()->TextWidth(0, 12,"00:00.0",-1);
// last 60 sec red, last 10 sec blink
if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit && Time <= 60)
{
float Alpha = Time <= 10 && (2*time_get()/time_freq()) % 2 ? 0.5f : 1.0f;
TextRender()->TextColor(1.0f, 0.25f, 0.25f, Alpha);
}
TextRender()->Text(0, Half-w/2, 2, FontSize, Buf, -1); TextRender()->Text(0, Half-w/2, 2, FontSize, Buf, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
} }
} }
@ -80,65 +87,132 @@ void CHud::RenderSuddenDeath()
void CHud::RenderScoreHud() void CHud::RenderScoreHud()
{ {
int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags;
float Whole = 300*Graphics()->ScreenAspect();
// render small score hud // render small score hud
if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) && (GameFlags&GAMEFLAG_TEAMS)) if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver))
{ {
char aScoreTeam[2][32]; int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags;
str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed); float Whole = 300*Graphics()->ScreenAspect();
str_format(aScoreTeam[TEAM_BLUE], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue);
float aScoreTeamWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_RED], -1), TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_BLUE], -1)};
float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1));
float Split = 3.0f;
float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split;
for(int t = 0; t < 2; t++) if(GameFlags&GAMEFLAG_TEAMS)
{ {
// draw box char aScoreTeam[2][32];
Graphics()->BlendNormal(); str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed);
Graphics()->TextureSet(-1); str_format(aScoreTeam[TEAM_BLUE], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue);
Graphics()->QuadsBegin(); float aScoreTeamWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_RED], -1), TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_BLUE], -1)};
if(t == 0) float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1));
Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f); float Split = 3.0f;
else float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split;
Graphics()->SetColor(0.0f, 0.0f, 1.0f, 0.25f);
RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L);
Graphics()->QuadsEnd();
// draw score for(int t = 0; t < 2; t++)
TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScoreTeam[t], -1);
if(GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_paFlags[t])
{ {
if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1))) // draw box
{ Graphics()->BlendNormal();
// draw flag Graphics()->TextureSet(-1);
Graphics()->BlendNormal(); Graphics()->QuadsBegin();
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); if(t == 0)
Graphics()->QuadsBegin(); Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f);
RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE); else
IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, 246.0f+t*20, ImageSize/2, ImageSize); Graphics()->SetColor(0.0f, 0.0f, 1.0f, 0.25f);
Graphics()->QuadsDrawTL(&QuadItem, 1); RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L);
Graphics()->QuadsEnd(); Graphics()->QuadsEnd();
}
else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
{
// draw name of the flag holder
int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
const char *pName = m_pClient->m_aClients[Id].m_aName;
float w = TextRender()->TextWidth(0, 10.0f, pName, -1);
TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-3*Split-w, 247.0f+t*20, 10.0f, pName, -1);
// draw tee of the flag holder // draw score
CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo; TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScoreTeam[t], -1);
Info.m_Size = 18.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), if(GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_paFlags[t])
vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20)); {
if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1)))
{
// draw flag
Graphics()->BlendNormal();
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
Graphics()->QuadsBegin();
RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE);
IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, 246.0f+t*20, ImageSize/2, ImageSize);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
}
else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
{
// draw name of the flag holder
int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
const char *pName = m_pClient->m_aClients[Id].m_aName;
float w = TextRender()->TextWidth(0, 10.0f, pName, -1);
TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-3*Split-w, 247.0f+t*20, 10.0f, pName, -1);
// draw tee of the flag holder
CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo;
Info.m_Size = 18.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20));
}
} }
} }
} }
else
{
int Local = 1;
int aPos[2] = { 1, 2 };
const CNetObj_PlayerInfo *apPlayerInfo[2] = { m_pClient->m_Snap.m_paInfoByScore[0], 0 };
if(m_pClient->m_Snap.m_paInfoByScore[0])
{
if(m_pClient->m_Snap.m_paInfoByScore[0]->m_ClientId == m_pClient->m_Snap.m_LocalCid)
{
apPlayerInfo[1] = m_pClient->m_Snap.m_paInfoByScore[1];
Local = 0;
}
else
for(int i = 1; i < MAX_CLIENTS; ++i)
if(m_pClient->m_Snap.m_paInfoByScore[i]->m_ClientId == m_pClient->m_Snap.m_LocalCid)
{
apPlayerInfo[1] = m_pClient->m_Snap.m_paInfoByScore[i];
aPos[1] = i+1;
break;
}
}
char aScore[2][32];
for(int t = 0; t < 2; ++t)
{
if(apPlayerInfo[t])
str_format(aScore[t], sizeof(aScore)/2, "%d", apPlayerInfo[t]->m_Score);
else
aScore[t][0] = 0;
}
float aScoreWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScore[0], -1), TextRender()->TextWidth(0, 14.0f, aScore[1], -1)};
float ScoreWidthMax = max(max(aScoreWidth[0], aScoreWidth[1]), TextRender()->TextWidth(0, 14.0f, "10", -1));
float Split = 3.0f, ImageSize = 16.0f, PosSize = 16.0f;
for(int t = 0; t < 2; t++)
{
// draw box
Graphics()->BlendNormal();
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
if(t == Local)
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
else
Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.25f);
RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f, 5.0f, CUI::CORNER_L);
Graphics()->QuadsEnd();
// draw score
TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScore[t], -1);
// draw tee
if(apPlayerInfo[t])
{
CTeeRenderInfo Info = m_pClient->m_aClients[apPlayerInfo[t]->m_ClientId].m_RenderInfo;
Info.m_Size = 18.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20));
}
// draw position
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%d.", aPos[t]);
TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, 247.0f+t*20, 10.0f, aBuf, -1);
}
}
} }
} }

View file

@ -1111,6 +1111,10 @@ void CMenus::SetActive(bool Active)
m_pClient->OnRelease(); m_pClient->OnRelease();
} }
} }
else if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
m_pClient->OnRelease();
}
} }
void CMenus::OnReset() void CMenus::OnReset()

View file

@ -498,6 +498,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0); ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0);
// server details // server details
CTextCursor Cursor;
const float FontSize = 12.0f; const float FontSize = 12.0f;
ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails); ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails);
RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
@ -545,15 +546,21 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
} }
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, pSelectedServer->m_aVersion, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aVersion, -1);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, pSelectedServer->m_aGameType, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aGameType, -1);
char aTemp[16]; char aTemp[16];
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency); str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, aTemp, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
} }
@ -579,11 +586,12 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard); ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard);
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score); str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score);
UI()->DoLabelScaled(&Row, aTemp, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = 25.0f;
TextRender()->TextEx(&Cursor, aTemp, -1);
Row.VSplitLeft(25.0f, 0x0, &Row); Row.VSplitLeft(25.0f, 0x0, &Row);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w; Cursor.m_LineWidth = Row.w;

View file

@ -130,8 +130,9 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
if(CurrentTick == TotalTicks) if(CurrentTick == TotalTicks)
{ {
DemoPlayer()->Pause(); m_pClient->OnReset();
DemoPlayer()->SetPos(0); DemoPlayer()->Pause();
DemoPlayer()->SetPos(0);
} }
if(m_MenuActive) if(m_MenuActive)
@ -160,6 +161,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
static int s_ResetButton = 0; static int s_ResetButton = 0;
if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button)) if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button))
{ {
m_pClient->OnReset();
DemoPlayer()->Pause(); DemoPlayer()->Pause();
DemoPlayer()->SetPos(0); DemoPlayer()->SetPos(0);
} }

View file

@ -128,6 +128,9 @@ void CScoreboard::RenderSpectators(float x, float y, float w)
void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle) void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle)
{ {
if(Team == TEAM_SPECTATORS)
return;
//float ystart = y; //float ystart = y;
float h = 750.0f; float h = 750.0f;
@ -150,61 +153,20 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
float Offset = 80.0f; float Offset = 80.0f;
float DataOffset = 130; float DataOffset = 130;
float tw = TextRender()->TextWidth(0, 48, pTitle, -1); float tw = TextRender()->TextWidth(0, 48, pTitle, -1);
TextRender()->Text(0, x+10, y, 48, pTitle, -1);
if(Team == TEAM_SPECTATORS) if(str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace"))
{ if(m_pClient->m_Snap.m_pGameobj)
TextRender()->Text(0, x+w/2-tw/2, y, 48, pTitle, -1); {
} char aBuf[128];
else int Score = Team == TEAM_RED ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed : m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue;
{ str_format(aBuf, sizeof(aBuf), "%d", Score);
TextRender()->Text(0, x+10, y, 48, pTitle, -1); tw = TextRender()->TextWidth(0, 48, aBuf, -1);
if(str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1);
if(m_pClient->m_Snap.m_pGameobj) }
{
char aBuf[128];
int Score = Team == TEAM_RED ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed : m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue;
str_format(aBuf, sizeof(aBuf), "%d", Score);
tw = TextRender()->TextWidth(0, 48, aBuf, -1);
TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1);
}
}
y += 54.0f; y += 54.0f;
// find players
const CNetObj_PlayerInfo *paPlayers[MAX_CLIENTS] = {0};
int NumPlayers = 0;
for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++)
{
IClient::CSnapItem Item;
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
{
const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
if(pInfo->m_Team == Team)
{
paPlayers[NumPlayers] = pInfo;
if(++NumPlayers == MAX_CLIENTS)
break;
}
}
}
// sort players
for(int k = 0; k < NumPlayers-1; k++) // ffs, bubblesort
{
for(int i = 0; i < NumPlayers-k-1; i++)
{
if((str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace") && (paPlayers[i]->m_Score < paPlayers[i+1]->m_Score)) || (!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace") && (m_pClient->m_aClients[paPlayers[i]->m_ClientId].m_Score == 0 || (m_pClient->m_aClients[paPlayers[i]->m_ClientId].m_Score > m_pClient->m_aClients[paPlayers[i+1]->m_ClientId].m_Score && m_pClient->m_aClients[paPlayers[i+1]->m_ClientId].m_Score != 0))))
{
const CNetObj_PlayerInfo *pTmp = paPlayers[i];
paPlayers[i] = paPlayers[i+1];
paPlayers[i+1] = pTmp;
}
}
}
// render headlines // render headlines
TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1); TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1);
if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace"))
@ -224,7 +186,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
float TeeSizeMod = 1.0f; float TeeSizeMod = 1.0f;
float TeeOffset = 0.0f; float TeeOffset = 0.0f;
if(NumPlayers > 13) if(m_pClient->m_Snap.m_aTeamSize[Team] > 13)
{ {
FontSize = 30.0f; FontSize = 30.0f;
LineHeight = 40.0f; LineHeight = 40.0f;
@ -233,9 +195,11 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
} }
// render player scores // render player scores
for(int i = 0; i < NumPlayers; i++) for(int i = 0; i < MAX_CLIENTS; i++)
{ {
const CNetObj_PlayerInfo *pInfo = paPlayers[i]; const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByScore[i];
if(!pInfo || pInfo->m_Team != Team)
continue;
// make sure that we render the correct team // make sure that we render the correct team
@ -422,8 +386,8 @@ void CScoreboard::OnRender()
else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed) else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed)
pText = Localize("Blue team wins!"); pText = Localize("Blue team wins!");
float w = TextRender()->TextWidth(0, 92.0f, pText, -1); float w = TextRender()->TextWidth(0, 86.0f, pText, -1);
TextRender()->Text(0, Width/2-w/2, 45, 92.0f, pText, -1); TextRender()->Text(0, Width/2-w/2, 39, 86.0f, pText, -1);
} }
RenderScoreboard(Width/2-w-20, 150.0f, w, TEAM_RED, Localize("Red team")); RenderScoreboard(Width/2-w-20, 150.0f, w, TEAM_RED, Localize("Red team"));

View file

@ -631,6 +631,12 @@ void CGameClient::OnGameOver()
Client()->AutoScreenshot_Start(); Client()->AutoScreenshot_Start();
} }
void CGameClient::OnStartGame()
{
if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
Client()->DemoRecorder_HandleAutoStart();
}
void CGameClient::OnRconLine(const char *pLine) void CGameClient::OnRconLine(const char *pLine)
{ {
m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine);
@ -821,6 +827,8 @@ void CGameClient::OnNewSnapshot()
m_Snap.m_pGameobj = (CNetObj_Game *)pData; m_Snap.m_pGameobj = (CNetObj_Game *)pData;
if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0) if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0)
OnGameOver(); OnGameOver();
else if(s_GameOver != 0 && m_Snap.m_pGameobj->m_GameOver == 0)
OnStartGame();
s_GameOver = m_Snap.m_pGameobj->m_GameOver; s_GameOver = m_Snap.m_pGameobj->m_GameOver;
} }
else if(Item.m_Type == NETOBJTYPE_FLAG) else if(Item.m_Type == NETOBJTYPE_FLAG)
@ -847,6 +855,21 @@ void CGameClient::OnNewSnapshot()
else else
m_Snap.m_Spectate = true; m_Snap.m_Spectate = true;
// sort player infos by score
mem_copy(m_Snap.m_paInfoByScore, m_Snap.m_paPlayerInfos, sizeof(m_Snap.m_paInfoByScore));
for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort
{
for(int i = 0; i < MAX_CLIENTS-k-1; i++)
{
if(m_Snap.m_paInfoByScore[i+1] && (!m_Snap.m_paInfoByScore[i] || m_Snap.m_paInfoByScore[i]->m_Score < m_Snap.m_paInfoByScore[i+1]->m_Score))
{
const CNetObj_PlayerInfo *pTmp = m_Snap.m_paInfoByScore[i];
m_Snap.m_paInfoByScore[i] = m_Snap.m_paInfoByScore[i+1];
m_Snap.m_paInfoByScore[i+1] = pTmp;
}
}
}
CTuningParams StandardTuning; CTuningParams StandardTuning;
CServerInfo CurrentServerInfo; CServerInfo CurrentServerInfo;
Client()->GetServerInfo(&CurrentServerInfo); Client()->GetServerInfo(&CurrentServerInfo);

View file

@ -187,6 +187,7 @@ public:
virtual void OnEnterGame(); virtual void OnEnterGame();
virtual void OnRconLine(const char *pLine); virtual void OnRconLine(const char *pLine);
virtual void OnGameOver(); virtual void OnGameOver();
virtual void OnStartGame();
virtual const char *GetItemName(int Type); virtual const char *GetItemName(int Type);
virtual const char *Version(); virtual const char *Version();

View file

@ -186,38 +186,38 @@ void CCharacter::HandleNinja()
// check if we Hit anything along the way // check if we Hit anything along the way
{ {
CCharacter *aEnts[64]; CCharacter *apEnts[64];
vec2 Dir = m_Pos - OldPos; vec2 Dir = m_Pos - OldPos;
float Radius = m_ProximityRadius * 2.0f; float Radius = m_ProximityRadius * 2.0f;
vec2 Center = OldPos + Dir * 0.5f; vec2 Center = OldPos + Dir * 0.5f;
int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, 64, NETOBJTYPE_CHARACTER); int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER);
for (int i = 0; i < Num; ++i) for (int i = 0; i < Num; ++i)
{ {
if (aEnts[i] == this) if (apEnts[i] == this)
continue; continue;
// make sure we haven't Hit this object before // make sure we haven't Hit this object before
bool bAlreadyHit = false; bool bAlreadyHit = false;
for (int j = 0; j < m_NumObjectsHit; j++) for (int j = 0; j < m_NumObjectsHit; j++)
{ {
if (m_apHitObjects[j] == aEnts[i]) if (m_apHitObjects[j] == apEnts[i])
bAlreadyHit = true; bAlreadyHit = true;
} }
if (bAlreadyHit) if (bAlreadyHit)
continue; continue;
// check so we are sufficiently close // check so we are sufficiently close
if (distance(aEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f)) if (distance(apEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f))
continue; continue;
// Hit a m_pPlayer, give him damage and stuffs... // Hit a m_pPlayer, give him damage and stuffs...
GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); GameServer()->CreateSound(apEnts[i]->m_Pos, SOUND_NINJA_HIT);
// set his velocity to fast upward (for now) // set his velocity to fast upward (for now)
if(m_NumObjectsHit < 10) if(m_NumObjectsHit < 10)
m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; m_apHitObjects[m_NumObjectsHit++] = apEnts[i];
aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); apEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA);
} }
} }
@ -329,39 +329,39 @@ void CCharacter::FireWeapon()
if (!g_Config.m_SvHit) break; if (!g_Config.m_SvHit) break;
CCharacter *aEnts[64]; CCharacter *apEnts[64];
int Hits = 0; int Hits = 0;
int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)aEnts, int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
64, NETOBJTYPE_CHARACTER); 64, NETOBJTYPE_CHARACTER);
for (int i = 0; i < Num; ++i) for (int i = 0; i < Num; ++i)
{ {
CCharacter *Target = aEnts[i]; CCharacter *pTarget = apEnts[i];
//for DDRace mod or any other mod, which needs hammer hits through the wall remove second condition //for DDRace mod or any other mod, which needs hammer hits through the wall remove second condition
if ((Target == this || !CanCollide(Target->GetPlayer()->GetCID())) /*|| GameServer()->Collision()->IntersectLine(ProjStartPos, Target->m_Pos, NULL, NULL)*/) if ((pTarget == this || !CanCollide(pTarget->GetPlayer()->GetCID())) /*|| GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)*/)
continue; continue;
// set his velocity to fast upward (for now) // set his velocity to fast upward (for now)
GameServer()->CreateHammerHit(m_Pos, Teams()->TeamMask(Team())); GameServer()->CreateHammerHit(m_Pos, Teams()->TeamMask(Team()));
aEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); apEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon);
vec2 Dir; vec2 Dir;
if (length(Target->m_Pos - m_Pos) > 0.0f) if (length(pTarget->m_Pos - m_Pos) > 0.0f)
Dir = normalize(Target->m_Pos - m_Pos); Dir = normalize(pTarget->m_Pos - m_Pos);
else else
Dir = vec2(0.f, -1.f); Dir = vec2(0.f, -1.f);
vec2 Temp = Target->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f * (m_HammerType + 1); vec2 Temp = pTarget->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f * (m_HammerType + 1);
if(Temp.x > 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_270) || (Target->m_TileIndexL == TILE_STOP && Target->m_TileFlagsL == ROTATION_270) || (Target->m_TileIndexL == TILE_STOPS && (Target->m_TileFlagsL == ROTATION_90 || Target->m_TileFlagsL ==ROTATION_270)) || (Target->m_TileIndexL == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_270) || (Target->m_TileFIndexL == TILE_STOP && Target->m_TileFFlagsL == ROTATION_270) || (Target->m_TileFIndexL == TILE_STOPS && (Target->m_TileFFlagsL == ROTATION_90 || Target->m_TileFFlagsL == ROTATION_270)) || (Target->m_TileFIndexL == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_270) || (Target->m_TileSIndexL == TILE_STOP && Target->m_TileSFlagsL == ROTATION_270) || (Target->m_TileSIndexL == TILE_STOPS && (Target->m_TileSFlagsL == ROTATION_90 || Target->m_TileSFlagsL == ROTATION_270)) || (Target->m_TileSIndexL == TILE_STOPA))) if(Temp.x > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOP && pTarget->m_TileFlagsL == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOPS && (pTarget->m_TileFlagsL == ROTATION_90 || pTarget->m_TileFlagsL ==ROTATION_270)) || (pTarget->m_TileIndexL == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOP && pTarget->m_TileFFlagsL == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOPS && (pTarget->m_TileFFlagsL == ROTATION_90 || pTarget->m_TileFFlagsL == ROTATION_270)) || (pTarget->m_TileFIndexL == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOP && pTarget->m_TileSFlagsL == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOPS && (pTarget->m_TileSFlagsL == ROTATION_90 || pTarget->m_TileSFlagsL == ROTATION_270)) || (pTarget->m_TileSIndexL == TILE_STOPA)))
Temp.x = 0; Temp.x = 0;
if(Temp.x < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_90) || (Target->m_TileIndexR == TILE_STOP && Target->m_TileFlagsR == ROTATION_90) || (Target->m_TileIndexR == TILE_STOPS && (Target->m_TileFlagsR == ROTATION_90 || Target->m_TileFlagsR == ROTATION_270)) || (Target->m_TileIndexR == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOP && Target->m_TileFFlagsR == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOPS && (Target->m_TileFFlagsR == ROTATION_90 || Target->m_TileFFlagsR == ROTATION_270)) || (Target->m_TileFIndexR == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOP && Target->m_TileSFlagsR == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOPS && (Target->m_TileSFlagsR == ROTATION_90 || Target->m_TileSFlagsR == ROTATION_270)) || (Target->m_TileSIndexR == TILE_STOPA))) if(Temp.x < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOP && pTarget->m_TileFlagsR == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOPS && (pTarget->m_TileFlagsR == ROTATION_90 || pTarget->m_TileFlagsR == ROTATION_270)) || (pTarget->m_TileIndexR == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOP && pTarget->m_TileFFlagsR == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOPS && (pTarget->m_TileFFlagsR == ROTATION_90 || pTarget->m_TileFFlagsR == ROTATION_270)) || (pTarget->m_TileFIndexR == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOP && pTarget->m_TileSFlagsR == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOPS && (pTarget->m_TileSFlagsR == ROTATION_90 || pTarget->m_TileSFlagsR == ROTATION_270)) || (pTarget->m_TileSIndexR == TILE_STOPA)))
Temp.x = 0; Temp.x = 0;
if(Temp.y < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_180) || (Target->m_TileIndexB == TILE_STOP && Target->m_TileFlagsB == ROTATION_180) || (Target->m_TileIndexB == TILE_STOPS && (Target->m_TileFlagsB == ROTATION_0 || Target->m_TileFlagsB == ROTATION_180)) || (Target->m_TileIndexB == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOP && Target->m_TileFFlagsB == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOPS && (Target->m_TileFFlagsB == ROTATION_0 || Target->m_TileFFlagsB == ROTATION_180)) || (Target->m_TileFIndexB == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOP && Target->m_TileSFlagsB == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOPS && (Target->m_TileSFlagsB == ROTATION_0 || Target->m_TileSFlagsB == ROTATION_180)) || (Target->m_TileSIndexB == TILE_STOPA))) if(Temp.y < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOP && pTarget->m_TileFlagsB == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOPS && (pTarget->m_TileFlagsB == ROTATION_0 || pTarget->m_TileFlagsB == ROTATION_180)) || (pTarget->m_TileIndexB == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOP && pTarget->m_TileFFlagsB == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOPS && (pTarget->m_TileFFlagsB == ROTATION_0 || pTarget->m_TileFFlagsB == ROTATION_180)) || (pTarget->m_TileFIndexB == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOP && pTarget->m_TileSFlagsB == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOPS && (pTarget->m_TileSFlagsB == ROTATION_0 || pTarget->m_TileSFlagsB == ROTATION_180)) || (pTarget->m_TileSIndexB == TILE_STOPA)))
Temp.y = 0; Temp.y = 0;
if(Temp.y > 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_0) || (Target->m_TileIndexT == TILE_STOP && Target->m_TileFlagsT == ROTATION_0) || (Target->m_TileIndexT == TILE_STOPS && (Target->m_TileFlagsT == ROTATION_0 || Target->m_TileFlagsT == ROTATION_180)) || (Target->m_TileIndexT == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOP && Target->m_TileFFlagsT == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOPS && (Target->m_TileFFlagsT == ROTATION_0 || Target->m_TileFFlagsT == ROTATION_180)) || (Target->m_TileFIndexT == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOP && Target->m_TileSFlagsT == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOPS && (Target->m_TileSFlagsT == ROTATION_0 || Target->m_TileSFlagsT == ROTATION_180)) || (Target->m_TileSIndexT == TILE_STOPA))) if(Temp.y > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOP && pTarget->m_TileFlagsT == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOPS && (pTarget->m_TileFlagsT == ROTATION_0 || pTarget->m_TileFlagsT == ROTATION_180)) || (pTarget->m_TileIndexT == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOP && pTarget->m_TileFFlagsT == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOPS && (pTarget->m_TileFFlagsT == ROTATION_0 || pTarget->m_TileFFlagsT == ROTATION_180)) || (pTarget->m_TileFIndexT == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOP && pTarget->m_TileSFlagsT == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOPS && (pTarget->m_TileSFlagsT == ROTATION_0 || pTarget->m_TileSFlagsT == ROTATION_180)) || (pTarget->m_TileSIndexT == TILE_STOPA)))
Temp.y = 0; Temp.y = 0;
Target->m_Core.m_Vel = Temp; pTarget->m_Core.m_Vel = Temp;
Target->UnFreeze(); pTarget->UnFreeze();
Hits++; Hits++;
} }
@ -373,7 +373,7 @@ void CCharacter::FireWeapon()
case WEAPON_GUN: case WEAPON_GUN:
{ {
CProjectile *Proj = new CProjectile CProjectile *pProj = new CProjectile
( (
GameWorld(), GameWorld(),
WEAPON_GUN,//Type WEAPON_GUN,//Type
@ -390,7 +390,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1); Msg.AddInt(1);
@ -418,7 +418,7 @@ void CCharacter::FireWeapon()
a += Spreading[i+2]; a += Spreading[i+2];
float v = 1-(absolute(i)/(float)ShotSpread); float v = 1-(absolute(i)/(float)ShotSpread);
float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v); float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
m_pPlayer->GetCID(), m_pPlayer->GetCID(),
ProjStartPos, ProjStartPos,
vec2(cosf(a), sinf(a))*Speed, vec2(cosf(a), sinf(a))*Speed,
@ -427,7 +427,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]); Msg.AddInt(((int *)&p)[i]);
@ -440,7 +440,7 @@ void CCharacter::FireWeapon()
case WEAPON_GRENADE: case WEAPON_GRENADE:
{ {
CProjectile *Proj = new CProjectile CProjectile *pProj = new CProjectile
( (
GameWorld(), GameWorld(),
WEAPON_GRENADE,//Type WEAPON_GRENADE,//Type
@ -457,7 +457,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1); Msg.AddInt(1);
@ -1166,15 +1166,15 @@ void CCharacter::HandleTiles(int Index)
m_Core.m_Vel = vec2(0,0); m_Core.m_Vel = vec2(0,0);
return; return;
} }
// handle death-tiles // handle death-tiles and leaving gamelayer
if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH)&& GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameLayerClipped(m_Pos)) &&
!m_Super) !m_Super)
{ {
Die(m_pPlayer->GetCID(), WEAPON_WORLD); Die(m_pPlayer->GetCID(), WEAPON_WORLD);

View file

@ -120,7 +120,7 @@ void CProjectile::Tick()
{ {
TeamMask = OwnerChar->Teams()->TeamMask( OwnerChar->Team()); TeamMask = OwnerChar->Teams()->TeamMask( OwnerChar->Team());
} }
if( ((TargetChr && (g_Config.m_SvHit || m_Owner == -1 || TargetChr == OwnerChar)) || Collide) && !isWeaponCollide)//TODO:TEAM if( ((TargetChr && (g_Config.m_SvHit || m_Owner == -1 || TargetChr == OwnerChar)) || Collide || GameLayerClipped(CurPos)) && !isWeaponCollide)//TODO:TEAM
{ {
if(m_Explosive/*??*/ && (!TargetChr || (TargetChr && !m_Freeze))) if(m_Explosive/*??*/ && (!TargetChr || (TargetChr && !m_Freeze)))
{ {

View file

@ -50,3 +50,9 @@ int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos)
return 1; return 1;
return 0; return 0;
} }
bool CEntity::GameLayerClipped(vec2 CheckPos)
{
return round(CheckPos.x)/32 < -200 || round(CheckPos.x)/32 > GameServer()->Collision()->GetWidth()+200 ||
round(CheckPos.y)/32 < -200 || round(CheckPos.y)/32 > GameServer()->Collision()->GetHeight()+200 ? true : false;
}

View file

@ -144,6 +144,7 @@ public:
int NetworkClipped(int SnappingClient); int NetworkClipped(int SnappingClient);
int NetworkClipped(int SnappingClient, vec2 CheckPos); int NetworkClipped(int SnappingClient, vec2 CheckPos);
bool GameLayerClipped(vec2 CheckPos);
/* /*
Variable: proximity_radius Variable: proximity_radius

View file

@ -92,8 +92,8 @@ void CGameControllerCTF::Tick()
if(!F) if(!F)
continue; continue;
// flag hits death-tile, reset it // flag hits death-tile or left the game layer, reset it
if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH) if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH || F->GameLayerClipped(F->m_Pos))
{ {
GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
F->Reset(); F->Reset();