diff --git a/.gitignore b/.gitignore index cba1fc094..5519db982 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,12 @@ +bam .bam config.lua datasrc/__pycache__ datasrc/*.pyc objs src/game/generated +SDL.dll +autoexec.cfg crapnet* dilate* @@ -23,7 +26,7 @@ buildlog.txt autoexec.cfg bam.exe *.bat -DDRace* +DDRace* DDRace-Server* .cproject .project diff --git a/data/editor/entities.png b/data/editor/entities.png index fa5e03ffa..20594db54 100644 Binary files a/data/editor/entities.png and b/data/editor/entities.png differ diff --git a/data/editor/front.png b/data/editor/front.png index 82874ccbe..ef31138d3 100644 Binary files a/data/editor/front.png and b/data/editor/front.png differ diff --git a/data/editor/switch.png b/data/editor/switch.png index 84e383fcb..63d0cf2f5 100644 Binary files a/data/editor/switch.png and b/data/editor/switch.png differ diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 78d12e9eb..dbf3b7c65 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -867,6 +867,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -882,6 +885,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -894,6 +900,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index 5abeb0879..ce243990f 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -858,6 +858,9 @@ Shift Show chat == +Sound error +== + Square == @@ -876,6 +879,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -891,6 +897,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index cadc9eb54..d03a15869 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -963,6 +963,15 @@ no limit Name plates size == +Sound error +== + +The audio device couldn't be initialised. +== + +Unable to delete the demo +== + ##### old translations ##### ##### DDRace ##### diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index 33ff92aa5..70783d71b 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -894,6 +900,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/french.txt b/data/languages/french.txt index 051eeb61e..a76ea7a42 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -286,9 +286,6 @@ Grenade Group == Groupe -HD -== HD - Hammer == Maillet @@ -900,6 +897,9 @@ Rotation of the envelope Shift == +Sound error +== + Squares the current quad == @@ -912,6 +912,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -924,6 +927,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Use Clipping == diff --git a/data/languages/german.txt b/data/languages/german.txt index bfb6c1571..f8d3c98d9 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -10,6 +10,18 @@ %ds left == Noch %ds +%i minute left +== Noch %i Minute + +%i minutes left +== Noch %i Minuten + +%i second left +== Noch %i Sekunde + +%i seconds left +== Noch %i Sekunden + %s Right click for context menu. == %s Rechtsklick für Kontextmenü. @@ -80,7 +92,7 @@ Automatically record demos == Automatisch Demos aufnehmen Automatically take game over screenshot -== Automatisch am Ende einer Runde ein Bildschirmfoto erstellen +== Bildschirmfotos autom. nach jeder Runde erstellen Blue team == Blaues Team @@ -484,6 +496,9 @@ Mute when not active Name == Name +Name plates size +== Größe der Namen + Name: == Name: @@ -602,7 +617,7 @@ Quads == Vier. Quality Textures -== Hochaufgelöste Texturen +== Hochauflösende Texturen Quick search: == Schnellsuche: @@ -763,6 +778,9 @@ Skins Sound == Ton +Sound error +== Audiofehler + Sound volume == Lautstärke @@ -811,6 +829,9 @@ Teeworlds %s is out! Download it at www.teeworlds.com! Texture Compression == Texturkompression +The audio device couldn't be initialised. +== Das Audiosystem konnte nicht gestartet werden. + The server is running a non-standard tuning on a pure game type. == Der Server läuft nicht mit Standardeinstellungen. @@ -841,6 +862,9 @@ Type UI Color == Menüfarbe +Unable to delete the demo +== Demo konnte nicht gelöscht werden + Up == Oben @@ -948,21 +972,6 @@ no limit ##### needs translation ##### -%i minute left -== - -%i minutes left -== - -%i second left -== - -%i seconds left -== - -Name plates size -== - ##### old translations ##### ##### DDRace ##### diff --git a/data/languages/index.txt b/data/languages/index.txt index a65bafc3b..2f3603847 100644 --- a/data/languages/index.txt +++ b/data/languages/index.txt @@ -28,12 +28,18 @@ polish portuguese == Português +romanian +== Română + russian == Русский serbian == Srpski +spanish +== Español + swedish == Svenska diff --git a/data/languages/italian.txt b/data/languages/italian.txt index 569fd228a..095c7f41e 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -4,26 +4,95 @@ %d of %d servers, %d players == %d di %d server, %d giocatori +%d%% loaded +== %d%% caricati + +%ds left +== %ds ancora + +%i minute left +== %i minuto ancora + +%i minutes left +== %i minuti ancora + +%i second left +== %i secondo ancora + +%i seconds left +== %i secondi ancora + +%s Right click for context menu. +== %s Menu tasto destro. + Abort == Annulla +Add +== Aggiungi + +Add Image +== +Immagine + +Add Quad +== +Forma + +Add group +== Aggiungi gruppo + +Add quads layer +== +Livello Forme + +Add tile layer +== +Livello Caselle + Address == Indirizzo +Adds a new group +== Aggiunge un nuovo Gruppo di Livelli + +Adds a new quad +== Aggiunge una nuova Forma nella mappa + All == Tutti Alpha == Alpha +Alpha value of the envelope +== Grafico dei valori di Trasparenza/Opacità (asse Y), in funzione del tempo (asse X) + Always show name plates == Mostra sempre etichette dei nomi +Anim +== Anim + +Append +== Inserisci + +Append map +== Inserisci Mappa + +Are you sure that you want to delete the demo? +== Sicuro di voler cancellare questa registrazione? + Are you sure that you want to quit? == Sicuro di voler uscire? 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. -== E' la prima volta che avvii il gioco, ti preghiamo di inserire il tuo nickname. E' consigliabile che tu controlli le impostazioni per aggiustarle in base alle tue preferenze prima di entrare in un server. +== E' la prima volta che avvii il gioco, ti preghiamo di inserire il tuo nickname. E' consigliato aggiustare le impostazioni in base alle proprie preferenze prima di entrare in un server. + +Aspect ratio +== Riproporziona + +Automatically record demos +== Registra demo automaticamente + +Automatically take game over screenshot +== Foto automatica a fine partita Blue team == Squadra Blu @@ -31,18 +100,60 @@ Blue team Blue team wins! == La squadra blu ha vinto! +Blue value of the envelope +== grafico dei valori di Blu (asse Y), in funzione del tempo (asse X) + Body == Corpo +Border +== Bordi + +CCW +== AS + +CW +== OD + Call vote == Inizia voto +Cancel +== Annulla + Chat == Chat +Clear collision +== Cancella collisioni + +Clip H +== Alt. Taglio + +Clip W +== Lar. Taglio + +Clip X +== Taglia da X + +Clip Y +== Taglia da Y + Close == Chiudi +Color +== Colore + +Color Env +== Eff. Col. + +Color TO +== a col. + +Color+ +== Colore + Compatible version == Versione compatibile @@ -52,12 +163,33 @@ Connect Connecting to == Connessione a +Connection Problems... +== Connessione Persa... + Console == Console +Constructs collision from this layer +== Costruisce le collisioni su questo livello + Controls == Controlli +Creates a new color envelope +== Crea un nuovo effetto di colore + +Creates a new map +== Crea una nuova mappa + +Creates a new pos envelope +== Crea un nuovo effetto di movimento + +Creates a new quad layer +== Crea un nuovo livello di forme + +Creates a new tile layer +== Crea un nuovo livello di caselle + Current == Attuale @@ -67,9 +199,39 @@ Current version: %s Custom colors == Colori personalizzati +Decrease +== Diminuisci + +Decrease animation speed +== Diminuisce la velocità dell'animazione + +Delete +== Cancella + +Delete demo +== Cancella demo + +Delete group +== Cancella gruppo + +Delete layer +== Cancella livello + +Delete this envelope +== Cancella quest'effetto + +Deletes the current quad +== Cancella la forma corrente + +Deletes the layer +== Cancella il livello selezionato + Demos == Demo +Detail +== Dettaglio + Disconnect == Disconnetti @@ -79,6 +241,9 @@ Disconnected Display Modes == Tipo di visualizzazione +Down +== Sotto + Downloading map == Scaricando la mappa @@ -88,12 +253,45 @@ Draw! Dynamic Camera == Visuale dinamica +Embed +== Incorpora + +Embedded +== Incorporate + +Embeds the image into the map file. +== Incorpora l'immagine nella mappa + Emoticon -== Emoticon +== Emozioni + +Enable/disable group for saving +== Includi/Escludi gruppo al salvataggio + +Enable/disable layer for saving +== Includi/Escludi livello al salvataggio Enter == Entra +Envelopes +== Effetti + +Error +== Errore + +Error loading demo +== Impossibile caricare la demo + +Exit +== Esci + +Exits from the editor +== Esci dall'editor + +External +== Esterne + FSAA samples == Esempi FSAA @@ -106,12 +304,21 @@ Favorites Feet == Piedi +Filename: +== Nome file: + Filter == Filtro Fire == Fuoco +Folder +== Cartella + +Force vote +== Forza voto + Fullscreen == Schermo intero @@ -134,17 +341,26 @@ General == Generale Graphics -== Grafiche +== Grafica + +Green value of the envelope +== Grafico dei valori di Verde (asse Y), in funzione del tempo (asse X) Grenade == Granata +Group +== Gruppo + Hammer == Martello Has people playing == Ha gente in gioco +Height +== Altezza + High Detail == Molti dettagli @@ -157,12 +373,27 @@ Host address Hue == Col. +Image +== Immagine + +Images +== Immagini + +Increase +== Aumenta + +Increase animation speed +== Aumenta la velocità dell'animazione + Info == Info Internet == Internet +Invalid Demo +== Demo non valida + Join blue == Entra blu @@ -184,15 +415,45 @@ LAN Language == Lingua +Layers +== Livelli + +Left +== Sinistra + +Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. +== Sposta la forma, +Shift per muovere il centro, +Ctrl per ruotarla. + +Left mouse button to move. Hold shift to move the texture. +== Sposta vertice, +Shift per adattare la trama interna. + +Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete. +== Trascina il punto, +Ctrl per aggiustare, +Shift sposta nel tempo. Tasto destro elimina il punto. + Lht. == Lum. +Load +== Carica... + +Load a new image to use in the map +== Carica una nuova immagine da usare nella mappa + +Load map +== Carica mappa + Loading == Caricamento MOTD == MDG +Make collision +== Ricalca collisioni + +Make external +== Scorpora + Map == Mappa @@ -220,11 +481,26 @@ Mute when not active Name == Nome +Name plates size +== Dimensione etichetta + +Name: +== Nome: + +New +== Nuovo + +New folder +== Nuova cartella + News == Notizie +Next Envelope +== Effetto successivo + Next weapon -== Prossima arma +== Successiva Nickname == Nickname @@ -241,9 +517,36 @@ No servers found No servers match your filter criteria == Nessun server corrisponde ai filtri di ricerca +None +== Nessuna + +Normal animation speed +== Imposta l'animazione alla velocità effettiva + Ok == Ok +Open +== Apri + +Opens a map and adds everything from that map to the current one +== Copia il contenuto di una mappa nella mappa corrente + +Opens a map for editing +== Apre una mappa per modificarla + +Order +== Ordine + +Para X +== Profond. X + +Para Y +== Profond. Y + +Parent Folder +== Indietro + Password == Password @@ -257,7 +560,7 @@ Pistol == Pistola Play -== Gioca +== Guarda Player == Giocatore @@ -265,8 +568,38 @@ Player Players == Giocatori +Please balance teams! +== Squadre sbilanciate! + +Pos X +== Coord. X + +Pos Y +== Coord. Y + +Pos. Env +== Eff. Mov. + +Pos. TO +== a Mov. + +Pos.+ +== Movim. + +Press right mouse button to create a new point +== Tasto destro per inserire un nuovo punto nel grafico + Prev. weapon -== Arma precedente +== Precedente + +Previous Envelope +== Effetto precedente + +Proof +== Schermi + +Quads +== Forme Quality Textures == Textures di qualità @@ -277,12 +610,24 @@ Quick search: Quit == Esci +Reason: +== Motivo: + +Record demo +== Registra demo + Red team == Squadra rossa Red team wins! == La squadra rossa ha vinto! +Red value of the envelope +== Grafico dei valori di Rosso (asse X), in funzione del tempo (asse Y) + +Refocus +== Riorienta + Refresh == Aggiorna @@ -292,15 +637,48 @@ Refreshing master servers Remote console == Console remota +Remove +== Rimuovi + +Removes collision from this layer +== Rimuove le collisioni presenti in questo livello + +Removes the image from the map +== Rivuove l'immagine dalla mappa + +Removes the image from the map file. +== Rimuove l'immagine dal file della mappa. + +Replace +== Rimpiazza + +Replace Image +== Sostituisci immagine + +Replaces the image with a new one +== Assegna a un'altra immagine il posto di questa + Reset filter == Annulla filtri Reset to defaults == Reimposta +Resizes the current Quad based on the aspect ratio of the image +== Ridimensiona la forma rispetto alle proporzioni dell'immagine associata al livello + Rifle == Laser +Right +== Destra + +Rotation of the brush in degrees. Use left mouse button to drag and change the value. Hold shift to be more precise. +== Ruota il pennello in gradi. Cambia valore scorrendo col tasto sinistro del mouse, +Shift per aggiustare. + +Rotation of the envelope +== Grafico dei valori di Rotazione (asse Y), in funzione del tempo (asse X) + Round == Turno @@ -310,6 +688,21 @@ Sample rate Sat. == Sat. +Save +== Salva + +Save As +== Salva come... + +Save map +== Salva le modifiche effettuate alla mappa + +Saves the current map +== Salva la mappa corrente + +Saves the current map under a new name +== Salva la mappa corrente con un altro nome + Score == Punti @@ -325,6 +718,15 @@ Scoreboard Screenshot == Screenshot +Select group. Right click for properties. +== Seleziona gruppo. + +Select image +== Seleziona immagine. + +Select layer. Right click for properties. +== Seleziona livello. + Server details == Dettagli del server @@ -338,7 +740,10 @@ Settings == Impostazioni Shotgun -== Shotgun +== Fucile + +Show chat +== Mostra Chat Show name plates == Mostra etichetta nomi @@ -361,12 +766,27 @@ Spectate Spectators == Spettatori +Square +== Squadra sagoma + +Squares the current quad +== Risquadra la forma corrente + Standard gametype == Tipo di gioco classico Standard map == Mappa classica +Stop record +== Termina reg. + +Switch between images and layers managment. +== Cambia l'area di intervento tra immagini o livelli. + +Switch curve type +== Cambia il tipo di curva + Switch weapon on pickup == Cambia arma alla raccolta @@ -382,12 +802,30 @@ Teeworlds %s is out! Download it at www.teeworlds.com! Texture Compression == Compressione Texture +The audio device couldn't be initialised. +== Il dispositivo audio non può essere inizializzato. + The server is running a non-standard tuning on a pure game type. == Il server sta eseguendo un tuning non-standard su un tipo di gioco classico. +Tiles +== Caselle + Time limit == Limite di tempo +Time limit: %d min +== Tempo limite %d min + +Toggle group visibility +== mostra/nasconde Gruppo + +Toggle layer visibility +== mostra/nasconde Livello + +Toggles the envelope editor. +== apre/allarga/chiude l'editor di Effetti grafici + Try again == Ritenta @@ -397,6 +835,27 @@ Type UI Color == Colore del menu +Unable to delete the demo +== Impossibile eliminare la registrazione + +Up +== Sopra + +Use Clipping +== Ritaglia + +Use left mouse button to drag and change the color value. Hold shift to be more precise. +== Cambia colore scorrendo col tasto sinistro del mouse, +Shift per aggiustare. + +Use left mouse button to drag and change the value. Hold shift to be more precise. +== Cambia valore scorrendo col tasto sinistro del mouse, +Shift per aggiustare. + +Use left mouse button to drag and create a brush. +== Seleziona una casella o un insieme da usare come pennello. + +Use left mouse button to paint with the brush. Right button clears the brush. +== Dipingi col tasto sinistro del mouse o pulisci pennello col destro. + Use sounds == Usa suoni @@ -416,10 +875,19 @@ Voting == Votazione Weapon -== Arma +== Attiva arma Welcome to Teeworlds -== Benvenuto su Teeworlds! +== Benvenuto su Teeworlds! + +Width +== Larghezza + +X-axis of the envelope +== Grafico dei valori di spostamento in orizzontale (asse Y), in funzione del tempo (asse X) + +Y-axis of the envelope +== Grafico dei valori di spostamento in verticale (asse Y), in funzione del tempo (asse X) Yes == Si @@ -427,542 +895,83 @@ Yes You must restart the game for all settings to take effect. == E' necessario riavviare il gioco per rendere effettive le modifiche. +Your skin +== La tua Skin + +ZI +== Z+ + +ZO +== Z- + +[HOME] Restore map focus +== [HOME] Ritorna al punto iniziale della mappa + +[M] Flip brush vertical +== [M] Specchia la selezione in verticale + +[N] Flip brush horizontal +== [N] Specchia la selezione in orizzontale + +[NumPad*] Zoom to normal and remove editor offset +== [NumPad*] Imposta la visuale alle dimensioni effettive + +[NumPad+] Zoom in +== [NumPad+] Ingrandisce la visuale + +[NumPad-] Zoom out +== [NumPad-] Rimpicciolisce la visuale + +[R] Rotates the brush counter clockwise +== [R] Ruota la selezione in senso antiorario + +[T] Rotates the brush clockwise +== [T] Ruota la selezione in senso orario + +[ctrl+h] Toggle High Detail +== [ctrl+h] Mostra/nasconde i Dettagli + +[ctrl+m] Toggle animation +== [ctrl+m] Avvia/Ferma l'animazione + +[ctrl+p] Toggles proof borders. These borders represent what a player maximum can see. +== [ctrl+p] Mostra/nasconde le dimensioni degli schermi comuni, e i limiti della visuale dinamica + +no limit +== senza limite + ##### needs translation ##### -%d%% loaded -== - -%ds left -== - -%i minute left -== - -%i minutes left -== - -%i second left -== - -%i seconds left -== - -%s Right click for context menu. -== - -Add -== - -Add Image -== - -Add Quad -== - -Add group -== - -Add quads layer -== - -Add tile layer -== - -Adds a new group -== - -Adds a new quad -== - -Alpha value of the envelope -== - -Anim -== - -Append -== - -Append map -== - -Are you sure that you want to delete the demo? -== - -Aspect ratio -== - -Automatically record demos -== - -Automatically take game over screenshot -== - -Blue value of the envelope -== - -Border -== - -CCW -== - -CW -== - -Cancel -== - -Clear collision -== - -Clip H -== - -Clip W -== - -Clip X -== - -Clip Y -== - -Color -== - -Color Env -== - -Color TO -== - -Color+ -== - -Connection Problems... -== - -Constructs collision from this layer -== - -Creates a new color envelope -== - -Creates a new map -== - -Creates a new pos envelope -== - -Creates a new quad layer -== - -Creates a new tile layer -== - -Decrease -== - -Decrease animation speed -== - -Delete -== - -Delete demo -== - -Delete group -== - -Delete layer -== - -Delete this envelope -== - -Deletes the current quad -== - -Deletes the layer -== - -Detail -== - -Down -== - -Embed -== - -Embedded -== - -Embeds the image into the map file. -== - -Enable/disable group for saving -== - -Enable/disable layer for saving -== - -Envelopes -== - -Error -== - -Error loading demo -== - -Exit -== - -Exits from the editor -== - -External -== - File == File: %s == -Filename: -== - -Folder -== - -Force vote -== - -Green value of the envelope -== - -Group -== - HD == -Height -== - -Image -== - -Images -== - -Increase -== - -Increase animation speed -== - -Invalid Demo -== - -Layers -== - -Left -== - -Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. -== - -Left mouse button to move. Hold shift to move the texture. -== - -Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete. -== - -Load -== - -Load a new image to use in the map -== - -Load map -== - -Make collision -== - -Make external -== - Max Screenshots == Max demos == -Name plates size -== - -Name: -== - -New -== - -New folder -== - -Next Envelope -== - -None -== - -Normal animation speed -== - -Open -== - -Opens a map and adds everything from that map to the current one -== - -Opens a map for editing -== - -Order -== - -Para X -== - -Para Y -== - -Parent Folder -== - -Please balance teams! -== - -Pos X -== - -Pos Y -== - -Pos. Env -== - -Pos. TO -== - -Pos.+ -== - -Press right mouse button to create a new point -== - -Previous Envelope -== - -Proof -== - -Quads -== - REC == -Reason: -== - -Record demo -== - -Red value of the envelope -== - -Refocus -== - -Remove -== - -Removes collision from this layer -== - -Removes the image from the map -== - -Removes the image from the map file. -== - -Replace -== - -Replace Image -== - -Replaces the image with a new one -== - -Resizes the current Quad based on the aspect ratio of the image -== - -Right -== - -Rotation of the brush in degrees. Use left mouse button to drag and change the value. Hold shift to be more precise. -== - -Rotation of the envelope -== - -Save -== - -Save As -== - -Save map -== - -Saves the current map -== - -Saves the current map under a new name -== - -Select group. Right click for properties. -== - -Select image -== - -Select layer. Right click for properties. -== - Shift == -Show chat -== - -Square -== - -Squares the current quad -== - -Stop record +Sound error == Sudden Death == -Switch between images and layers managment. -== - -Switch curve type -== - -Tiles -== - -Time limit: %d min -== - -Toggle group visibility -== - -Toggle layer visibility -== - -Toggles the envelope editor. -== - -Up -== - -Use Clipping -== - -Use left mouse button to drag and change the color value. Hold shift to be more precise. -== - -Use left mouse button to drag and change the value. Hold shift to be more precise. -== - -Use left mouse button to drag and create a brush. -== - -Use left mouse button to paint with the brush. Right button clears the brush. -== - Warmup == -Width -== - -X-axis of the envelope -== - -Y-axis of the envelope -== - -Your skin -== - -ZI -== - -ZO -== - -[HOME] Restore map focus -== - -[M] Flip brush vertical -== - -[N] Flip brush horizontal -== - -[NumPad*] Zoom to normal and remove editor offset -== - -[NumPad+] Zoom in -== - -[NumPad-] Zoom out -== - -[R] Rotates the brush counter clockwise -== - -[T] Rotates the brush clockwise -== - -[ctrl+h] Toggle High Detail -== - -[ctrl+m] Toggle animation -== - -[ctrl+p] Toggles proof borders. These borders represent what a player maximum can see. -== - -no limit -== - ##### old translations ##### ##### DDRace ##### diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 1380a1e1e..2d9c61ee5 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -930,15 +930,24 @@ Rotation of the envelope Shift == +Sound error +== + Stop record == +The audio device couldn't be initialised. +== + Tiles == Time limit: %d min == +Unable to delete the demo +== + Up == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index 5ec214b93..47d1b3a73 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -894,6 +900,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt new file mode 100644 index 000000000..32e1011b9 --- /dev/null +++ b/data/languages/romanian.txt @@ -0,0 +1,976 @@ + +##### 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 + +Unable to delete the demo +== Nu pot șterge demo-ul + +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 ##### + +Sound error +== + +The audio device couldn't be initialised. +== + +##### old translations ##### + diff --git a/data/languages/russian.txt b/data/languages/russian.txt index 53165a806..11e1f79a9 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -930,15 +930,24 @@ Rotation of the envelope Shift == +Sound error +== + Stop record == +The audio device couldn't be initialised. +== + Tiles == Time limit: %d min == +Unable to delete the demo +== + Up == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 63b8f87a3..33ca37625 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -894,6 +900,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt new file mode 100644 index 000000000..4896f434b --- /dev/null +++ b/data/languages/spanish.txt @@ -0,0 +1,976 @@ + +##### translated strings ##### + +%d of %d servers, %d players +== %d de %d servidores, %d jugadores + +%d%% loaded +== %d%% cargado + +%ds left +== faltan %ds + +%i minute left +== %i minuto falta + +%i minutes left +== %i minutos faltan + +%i second left +== %i segundo falta + +%i seconds left +== %i segundos faltan + +%s Right click for context menu. +== %s click derecho para ver menu. + +Abort +== Cancelar + +Add +== Agregar + +Add Image +== Agregar imagen + +Add Quad +== Agregar campo + +Add group +== Agregar grupo + +Add quads layer +== Agregar campo capa + +Add tile layer +== Agregar capa de suelo + +Address +== Dirección + +Adds a new group +== Agregar nuevo grupo + +Adds a new quad +== Agregar nuevo campo + +All +== Todos + +Alpha +== Alpha + +Alpha value of the envelope +== Valor alpha de la envoltura + +Always show name plates +== Siempre mostrar apodos + +Anim +== Animación + +Append +== Anexar + +Append map +== Anexar mapa + +Are you sure that you want to delete the demo? +== Seguro de eliminar la demo? + +Are you sure that you want to quit? +== Seguro que desea salir? + +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. +== Como es la primera vez que abre el juego, por favor, entre con su apodo. Es recomendable que verifique su configuración y ajuste las preferencias antes de entrar en un servidor. + +Aspect ratio +== Relación de aspecto + +Automatically record demos +== Registro automático en demos + +Automatically take game over screenshot +== Pantalla game over automáticamente + +Blue team +== Equipo azul + +Blue team wins! +== Equipo azul gana! + +Blue value of the envelope +== Valor azul de la envoltura + +Body +== Cuerpo + +Border +== Bordes + +CCW +== CCW + +CW +== CW + +Call vote +== Votación + +Cancel +== Cancelar + +Chat +== Charla + +Clear collision +== Limpiar colisión + +Clip H +== Clip H + +Clip W +== Clip W + +Clip X +== Clip X + +Clip Y +== Clip Y + +Close +== Cerrar + +Color +== Color + +Color Env +== Color Env + +Color TO +== Color TO + +Color+ +== Color+ + +Compatible version +== Versión compatible + +Connect +== Conectar + +Connecting to +== Conectando a + +Connection Problems... +== Problemas de Conexión... + +Console +== Consola + +Constructs collision from this layer +== Construir collisión para esta capa + +Controls +== Controles + +Creates a new color envelope +== Crear nuevo color de envoltura + +Creates a new map +== Crear nuevo mapa + +Creates a new pos envelope +== Crear nueva envoltura + +Creates a new quad layer +== Crear nueva capa de campo + +Creates a new tile layer +== Crear nueva capa de suelo + +Current +== Actualmente + +Current version: %s +== Versión actual: %s + +Custom colors +== Colores personalizados + +Decrease +== Reducir + +Decrease animation speed +== Reducir velocidad de animación + +Delete +== Borrar + +Delete demo +== Borrar demo + +Delete group +== Borrar grupo + +Delete layer +== Borrar capa + +Delete this envelope +== Borrar envoltura + +Deletes the current quad +== Borrar el campo actual + +Deletes the layer +== Borrada la capa + +Demos +== Demos + +Detail +== Detalles + +Disconnect +== Desconectar + +Disconnected +== Desconectado + +Display Modes +== Modos de exibición + +Down +== Abajo + +Downloading map +== Bajando mapa + +Draw! +== Empate! + +Dynamic Camera +== Cámara dinámica + +Embed +== Integrar + +Embedded +== Embebido + +Embeds the image into the map file. +== Integrar la imagen en el mapa + +Emoticon +== Emoticon + +Enable/disable group for saving +== Activar/Desactivar guardar grupo + +Enable/disable layer for saving +== Activar/Desactivar guardar capa + +Enter +== Entrar + +Envelopes +== Envolturas + +Error +== Error + +Error loading demo +== Error al cargar demo + +Exit +== Salir + +Exits from the editor +== Salir del editor + +External +== Exterior + +FSAA samples +== Muestras FSAA + +Favorite +== Favorito + +Favorites +== Favoritos + +Feet +== Pies + +File +== Archivo + +File: %s +== Archivo: %s + +Filename: +== Archivo: + +Filter +== Filtro + +Fire +== Disparar + +Folder +== Carpeta + +Force vote +== Forzar + +Fullscreen +== Pantalla Completa + +Game +== Juego + +Game info +== Info. sobre el juego + +Game over +== Fin de Juego + +Game type +== Tipo de juego + +Game types: +== Tipos de juego: + +General +== General + +Graphics +== Gráficos + +Green value of the envelope +== Valor verde de la envoltura + +Grenade +== Granada + +Group +== Grupo + +HD +== HD + +Hammer +== Martillo + +Has people playing +== Hay gente jugando + +Height +== Alto + +High Detail +== Mas detalles (HD) + +Hook +== Gancho + +Host address +== Dirección de host + +Hue +== Matiz + +Image +== Imagen + +Images +== Imagenes + +Increase +== Incrementar + +Increase animation speed +== Incrementar velocidad animación + +Info +== Info. + +Internet +== Internet + +Invalid Demo +== Demo invalida + +Join blue +== Azul + +Join game +== Entrar en juego + +Join red +== Rojo + +Jump +== Saltar + +Kick +== Golpeo + +LAN +== LAN + +Language +== Lenguaje + +Layers +== Capas + +Left +== Izquierda + +Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. +== Izquierdo del ratón para mover. Mantenga mayúsculas para pivotar. Mantenga control para rotar. + +Left mouse button to move. Hold shift to move the texture. +== Izquierdo del ratón para mover. Mantenga mayúsculas para mover la textura. + +Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete. +== Izquierdo del ratón para arrastrar. Mantén pulsado Ctrl para ser más precisos. Mantenga mayúsculas para modificar el tiempo también. Derecho del ratón para eliminar. + +Lht. +== Luz + +Load +== Carga + +Load a new image to use in the map +== Carga nueva imagen para usar en el mapa + +Load map +== Cargar mapa + +Loading +== Cargando + +MOTD +== MOTD + +Make collision +== Fabricar colisión + +Make external +== Fabricar exterior + +Map +== Mapa + +Max Screenshots +== Max capturas + +Max demos +== Max demos + +Maximum ping: +== Ping máximo: + +Miscellaneous +== Miscelanea + +Mouse sens. +== Sens. o ratón + +Move left +== Izquierda + +Move right +== Derecha + +Movement +== Movimiento + +Mute when not active +== Silenciar en inactivo + +Name +== Nombre + +Name plates size +== Tamaño del nombre de placas + +Name: +== Nombre: + +New +== Nuevo + +New folder +== Nueva carpeta + +News +== Notícia + +Next Envelope +== Nueva encoltura + +Next weapon +== Próxima arma + +Nickname +== Apodo + +No +== No + +No password +== Sin contraseña + +No servers found +== Ningún servidor encontrado + +No servers match your filter criteria +== Ningún servidor corresponde a los critérios de filtro + +None +== Ninguno + +Normal animation speed +== Velocidad de animación normal + +Ok +== Ok + +Open +== Abrir + +Opens a map and adds everything from that map to the current one +== Abrir mapa y añade todo desde otro mapa al actual + +Opens a map for editing +== Abrir mapa para editar + +Order +== Pedir + +Para X +== Para X + +Para Y +== Para Y + +Parent Folder +== Carpeta superior + +Password +== Contraseña + +Password incorrect +== Contraseña incorreta + +Ping +== Ping + +Pistol +== Pistola + +Play +== Asistir + +Player +== Jugador + +Players +== Jugadores + +Please balance teams! +== Por favor, equilibre los equipos! + +Pos X +== Pos X + +Pos Y +== Pos Y + +Pos. Env +== Pos. Env + +Pos. TO +== Pos. TO + +Pos.+ +== Pos.+ + +Press right mouse button to create a new point +== Pulse el botón derecho del ratón para crear un nuevo punto + +Prev. weapon +== Arma anterior + +Previous Envelope +== Envoltura anterior + +Proof +== Prueba + +Quads +== Campos + +Quality Textures +== Texturas de calidad + +Quick search: +== Pesquisa rápida: + +Quit +== Salir + +REC +== REC + +Reason: +== Razón: + +Record demo +== Registro demo + +Red team +== Equipo rojo + +Red team wins! +== Equipo rojo gana! + +Red value of the envelope +== Valor rojo de la envoltura + +Refocus +== Reorientar + +Refresh +== Actualizar + +Refreshing master servers +== Actualizando servidores master + +Remote console +== Consola remota + +Remove +== Remover + +Removes collision from this layer +== Remover colisión para esta capa + +Removes the image from the map +== Remover la imagen de este mapa + +Removes the image from the map file. +== Remover la imagen para este archivo de mapa. + +Replace +== Reemplazar + +Replace Image +== Reemplazar Imagen + +Replaces the image with a new one +== Reemplazar imagen con una nueva + +Reset filter +== Resetar filtro + +Reset to defaults +== Resetar por defecto + +Resizes the current Quad based on the aspect ratio of the image +== Redimensionar el actual campo según la dimensión de imagen + +Rifle +== Laser + +Right +== Derecha + +Rotation of the brush in degrees. Use left mouse button to drag and change the value. Hold shift to be more precise. +== Rotación del pincel en grados. Utilice el botón izquierdo del ratón para arrastrar y cambiar el valor. Mantenga mayúsculas para ser más precisos. + +Rotation of the envelope +== Rotacion de la envoltura + +Round +== Ronda + +Sample rate +== Frecuencia de muestreo + +Sat. +== Sat. + +Save +== Guardar + +Save As +== Guardar como + +Save map +== Guardar mapa + +Saves the current map +== Guardar el mapa actual + +Saves the current map under a new name +== Guardar el mapa actual en un nuevo juego + +Score +== Puntos + +Score board +== Tabla de puntos + +Score limit +== Puntos máx. + +Scoreboard +== Puntuación + +Screenshot +== Captura da pantalla + +Select group. Right click for properties. +== Seleccionar grupo. Botón derecho para propiedades. + +Select image +== Seleccionar imagen + +Select layer. Right click for properties. +== Seleccionar capa. Botón derecho para propiedades. + +Server details +== Detalles del server + +Server info +== Info del server + +Server not full +== Servidor incompleto + +Settings +== Config. + +Shift +== Mayúscula + +Shotgun +== Escopeta + +Show chat +== Mostrar chat + +Show name plates +== Mostrar nicks + +Show only supported +== Mostrar solo soportados + +Skins +== Skins + +Sound +== Sonido + +Sound error +== Error de sonido + +Sound volume +== Volumem de sonido + +Spectate +== Observar + +Spectators +== Observadores + +Square +== Cuadro + +Squares the current quad +== Cuadros del campo actual + +Standard gametype +== Tipo de juego normal + +Standard map +== Mapa normal + +Stop record +== Parar grabación + +Sudden Death +== Muerte Súbita + +Switch between images and layers managment. +== Cambiar entre las imágenes y la gestión de capas. + +Switch curve type +== Interruptor tipo curva + +Switch weapon on pickup +== Cambiar de arma + +Team +== Equipo + +Team chat +== Conv. de equipo + +Teeworlds %s is out! Download it at www.teeworlds.com! +== Teeworlds %s ya salió! Descárgalo desde www.teeworlds.com! + +Texture Compression +== Compresión de Textura + +The audio device couldn't be initialised. +== El dispositivo de audio no puede ser inicializado. + +The server is running a non-standard tuning on a pure game type. +== El servidor está ejecutando una afinación no estándar en un tipo de juego puro. + +Tiles +== Suelos + +Time limit +== Tiempo máx. + +Time limit: %d min +== Tiempo limite: %d min + +Toggle group visibility +== Cambiar la visibilidad del grupo + +Toggle layer visibility +== Alternar la visibilidad de capa + +Toggles the envelope editor. +== Cambia el editor de envoltura. + +Try again +== Probar de nuevo + +Type +== Tipo + +UI Color +== Color de menu + +Unable to delete the demo +== No se puede eliminar la demo + +Up +== Arriba + +Use Clipping +== Usar Tijretazo + +Use left mouse button to drag and change the color value. Hold shift to be more precise. +== Utilice el botón izquierdo del ratón para arrastrar y cambiar el valor del color. Mantenga cambio para ser más precisos. + +Use left mouse button to drag and change the value. Hold shift to be more precise. +== Utilice el botón izquierdo del ratón para arrastrar y cambiar el valor. Mantenga cambio para ser más precisos. + +Use left mouse button to drag and create a brush. +== Utilice el botón izquierdo del ratón para arrastrar y crear un pincel. + +Use left mouse button to paint with the brush. Right button clears the brush. +== Utilice el botón izquierdo del ratón para pintar con el pincel. Botón derecho despeja el pincel. + +Use sounds +== Usar sonidos + +V-Sync +== V-Sync + +Version +== Versión + +Vote no +== Votar no + +Vote yes +== Votar si + +Voting +== Votando + +Warmup +== Calentamiento + +Weapon +== Arma + +Welcome to Teeworlds +== Bienvenido a Teeworlds! + +Width +== Ancho + +X-axis of the envelope +== eje-X de la envoltura + +Y-axis of the envelope +== eje-Y de la encoltura + +Yes +== Si + +You must restart the game for all settings to take effect. +== Debes reiniciar el juego para que los cambios tengan efecto. + +Your skin +== Tu skin + +ZI +== ZI + +ZO +== ZO + +[HOME] Restore map focus +== [HOME] Restaurar mapa + +[M] Flip brush vertical +== [M] Flip pincel vertical + +[N] Flip brush horizontal +== [N] Flip pincel horizontal + +[NumPad*] Zoom to normal and remove editor offset +== [NumPad*] Zoom a la normalidad y eliminar editor de desplazamiento + +[NumPad+] Zoom in +== [NumPad+] Acercar Zoom + +[NumPad-] Zoom out +== [NumPad-] Alejar Zoom + +[R] Rotates the brush counter clockwise +== [R] Rotar a la izquierda el pincel + +[T] Rotates the brush clockwise +== [T] Rotar a la derecha el pincel + +[ctrl+h] Toggle High Detail +== [ctrl+h] Activar detalle alto + +[ctrl+m] Toggle animation +== [ctrl+m] Activar animación + +[ctrl+p] Toggles proof borders. These borders represent what a player maximum can see. +== [ctrl+p] Alterna bordes de prueba. Estas fronteras representan lo que un jugador puede ver máximo. + +no limit +== sin límite + +##### needs translation ##### + +##### old translations ##### + diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 330444a96..c73e9b789 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -855,6 +855,9 @@ Shift Show chat == +Sound error +== + Square == @@ -873,6 +876,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == @@ -888,6 +894,9 @@ Toggle layer visibility Toggles the envelope editor. == +Unable to delete the demo +== + Up == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index bc9b1de87..518e76397 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -945,6 +945,15 @@ Rotation of the envelope Shift == +Sound error +== + +The audio device couldn't be initialised. +== + +Unable to delete the demo +== + Up == diff --git a/data/mapres/entities.png b/data/mapres/entities.png index cf2730cf5..988f5140a 100644 Binary files a/data/mapres/entities.png and b/data/mapres/entities.png differ diff --git a/scripts/cmd5.py b/scripts/cmd5.py index dbdfae824..11a18137d 100644 --- a/scripts/cmd5.py +++ b/scripts/cmd5.py @@ -31,6 +31,6 @@ for filename in sys.argv[1:]: hash = hashlib.md5(f.encode()).hexdigest().lower()[16:] # TODO: refactor hash that is equal to the 0.5 hash, remove when we # TODO: remove when we don't need it any more -if hash == "026b8eceb4cdd369": +if hash == "f16c2456fc487748": hash = "b67d1f1a1eea234e" print('#define GAME_NETVERSION_HASH "%s"' % hash) diff --git a/scripts/update_localization.py b/scripts/update_localization.py index 6baa6d47e..61fb6c5b9 100644 --- a/scripts/update_localization.py +++ b/scripts/update_localization.py @@ -8,8 +8,8 @@ source_exts = [".c", ".cpp", ".h"] def parse_source(): stringtable = {} def process_line(line): - if 'Localize("' in line: - fields = line.split('Localize("', 1)[1].split('"', 1) + if b'Localize("' in line: + fields = line.split(b'Localize("', 1)[1].split(b'"', 1) stringtable[fields[0]] = "" process_line(fields[1]) @@ -23,21 +23,21 @@ def parse_source(): if filename[-2:] in source_exts or filename[-4:] in source_exts: for line in open(filename, "rb"): process_line(line) - + return stringtable def load_languagefile(filename): f = open(filename, "rb") lines = f.readlines() f.close() - + stringtable = {} for i in range(0, len(lines)-1): - l = lines[i].decode("utf-8").strip() - if len(l) and not l[0] == '=' and not l[0] == '#': - stringtable[l] = lines[i+1][3:].decode("utf-8").rstrip() - + l = lines[i].strip() + if len(l) and not l[0:1] == b"=" and not l[0:1] == b"#": + stringtable[l] = lines[i+1][3:].rstrip() + return stringtable def generate_languagefile(outputfilename, srctable, loctable): @@ -52,28 +52,27 @@ def generate_languagefile(outputfilename, srctable, loctable): srctable_keys.append(key) srctable_keys.sort() - content = "\n##### translated strings #####\n\n" + content = b"\n##### translated strings #####\n\n" for k in srctable_keys: 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 - - content += "##### needs translation #####\n\n" + content += b"##### needs translation #####\n\n" for k in srctable_keys: 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 new_items += 1 - content += "##### old translations #####\n\n" + content += b"##### old translations #####\n\n" for k in loctable: 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 old_items += 1 - - f.write(content.encode("utf-8")) + + f.write(content) f.close() print("%-40s %8d %8d %8d" % (outputfilename, num_items, new_items, old_items)) @@ -86,6 +85,6 @@ for filename in os.listdir("../data/languages"): continue if filename == "index.txt": continue - + filename = "../data/languages/" + filename generate_languagefile(filename, srctable, load_languagefile(filename)) diff --git a/src/engine/client.h b/src/engine/client.h index ab1f05479..2da2bd8b7 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -77,6 +77,7 @@ public: virtual void Quit() = 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_HandleAutoStart() = 0; virtual void DemoRecorder_Stop() = 0; virtual void AutoScreenshot_Start() = 0; @@ -129,6 +130,8 @@ public: virtual const char *ErrorString() = 0; virtual const char *LatestVersion() = 0; virtual bool ConnectionProblems() = 0; + + virtual bool SoundInitFailed() = 0; }; class IGameClient : public IInterface @@ -148,6 +151,7 @@ public: virtual void OnConnected() = 0; virtual void OnMessage(int MsgId, CUnpacker *pUnpacker) = 0; virtual void OnPredict() = 0; + virtual void OnActivateEditor() = 0; virtual int OnSnapInput(int *pData) = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 948feca20..c356c9238 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -414,6 +414,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_WindowMustRefocus = 0; m_SnapCrcErrors = 0; m_AutoScreenshotRecycle = false; + m_EditorActive = false; m_AckGameTick = -1; m_CurrentRecvTick = 0; @@ -1466,11 +1467,11 @@ void CClient::ProcessPacket(CNetChunk *pPacket) } // adjust game time + if(m_RecivedSnapshots > 2) { int64 Now = m_GameTime.Get(time_get()); int64 TickStart = GameTick*time_freq()/50; int64 TimeLeft = (TickStart-Now)*1000 / time_freq(); - //st_update(&game_time, (game_tick-1)*time_freq()/50); m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0); } @@ -1807,7 +1808,7 @@ void CClient::Run() m_pEditor->Init(); // init sound, allowed to fail - Sound()->Init(); + m_SoundInitFailed = Sound()->Init() != 0; // load data if(!LoadData()) @@ -1919,12 +1920,21 @@ void CClient::Run() // render if(g_Config.m_ClEditor) { + if(!m_EditorActive) + { + GameClient()->OnActivateEditor(); + m_EditorActive = true; + } + Update(); m_pEditor->UpdateAndRender(); m_pGraphics->Swap(); } else { + if(m_EditorActive) + m_EditorActive = false; + Update(); if(g_Config.m_DbgStress) @@ -2159,6 +2169,7 @@ void CClient::DemoRecorder_HandleAutoStart() { if(g_Config.m_ClAutoDemoRecord) { + DemoRecorder_Stop(); DemoRecorder_Start("auto/autorecord", true); if(g_Config.m_ClAutoDemoMax) { diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 12a2e9ae4..9d3687706 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -141,6 +141,8 @@ class CClient : public IClient, public CDemoPlayer::IListner int m_WindowMustRefocus; int m_SnapCrcErrors; bool m_AutoScreenshotRecycle; + bool m_EditorActive; + bool m_SoundInitFailed; int m_AckGameTick; int m_CurrentRecvTick; @@ -234,6 +236,8 @@ public: virtual bool ConnectionProblems(); + virtual bool SoundInitFailed() { return m_SoundInitFailed; } + void DirectInput(int *pInput, int Size); void SendInput(); diff --git a/src/engine/client/srvbrowse.cpp b/src/engine/client/srvbrowse.cpp index 0041bcd03..7196edee7 100644 --- a/src/engine/client/srvbrowse.cpp +++ b/src/engine/client/srvbrowse.cpp @@ -2,6 +2,7 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include // sort +#include #include #include #include @@ -449,9 +450,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer { SetInfo(pEntry, *pInfo); if(m_ServerlistType == IServerBrowser::TYPE_LAN) - pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-m_BroadcastTime)*1000/time_freq()), 999); else - pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999); RemoveRequest(pEntry); } } @@ -463,9 +464,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer SetInfo(pEntry, *pInfo); if(m_ServerlistType == IServerBrowser::TYPE_LAN) - pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-m_BroadcastTime)*1000/time_freq()), 999); else - pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999); RemoveRequest(pEntry); } } @@ -748,4 +749,4 @@ void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData) str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr); pConfig->WriteLine(aBuffer); } -} \ No newline at end of file +} diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index 828aa3fd6..d24c41aef 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -688,21 +688,20 @@ public: 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) { 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); 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; diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index dfa3060f3..36b26f1e1 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -187,7 +187,7 @@ void CRegister::RegisterUpdate() else { char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "choosen '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer)); + str_format(aBuf, sizeof(aBuf), "chose '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer)); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = 0; RegisterNewState(REGISTERSTATE_HEARTBEAT); diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index f0b0b9afe..d8050ce8b 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -190,6 +190,8 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_MapReload = 0; + memset(m_aPrevStates, CClient::STATE_EMPTY, MAX_CLIENTS * sizeof(int)); + m_RconClientId = -1; Init(); @@ -591,6 +593,7 @@ int CServer::DelClientCallback(int ClientId, const char *pReason, void *pUser) pThis->m_aClients[ClientId].m_aClan[0] = 0; pThis->m_aClients[ClientId].m_Authed = 0; pThis->m_aClients[ClientId].m_AuthTries = 0; + pThis->m_aPrevStates[ClientId] = CClient::STATE_EMPTY; memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR)); pThis->m_aClients[ClientId].m_Snapshots.PurgeAll(); return 0; @@ -631,14 +634,14 @@ void CServer::SendRconLineAuthed(const char *pLine, void *pUser) void CServer::SendRconResponse(const char *pLine, void *pUser) { - RconResponseInfo *pInfo = (RconResponseInfo *)pUser; - CServer *pThis = pInfo->m_Server; + RconResponseInfo *pInfo = (RconResponseInfo *)pUser; + CServer *pThis = pInfo->m_Server; static volatile int ReentryGuard = 0; if(ReentryGuard) - return; + return; - ReentryGuard++; + ReentryGuard++; if(pThis->m_aClients[pInfo->m_ClientId].m_State != CClient::STATE_EMPTY) pThis->SendRconLine(pInfo->m_ClientId, pLine); @@ -903,22 +906,24 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else { - char aHex[] = "0123456789ABCDEF"; - char aBuf[512]; - - for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) + if(g_Config.m_Debug) { - aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; - aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; - aBuf[b*3+2] = ' '; - aBuf[b*3+3] = 0; - } + char aHex[] = "0123456789ABCDEF"; + char aBuf[512]; - char aBufMsg[256]; - str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); - + for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) + { + aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; + aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; + aBuf[b*3+2] = ' '; + aBuf[b*3+3] = 0; + } + + char aBufMsg[256]; + str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBufMsg); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); + } } } else @@ -1145,6 +1150,11 @@ int CServer::LoadMap(const char *pMapName) io_read(File, m_pCurrentMapData, m_CurrentMapSize); io_close(File); } + + for(int i=0; iGetString(0); int Minutes = 30; - const char *pReason = "No reason given"; + const char *pReason = "No reason given"; if(pResult->NumArguments() > 1) Minutes = pResult->GetInteger(1); @@ -1394,7 +1404,7 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1) Addr.port = AddrCheck.port = 0; if(net_addr_comp(&Addr, &AddrCheck) == 0) { - pServer->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban yourself"); + pServer->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can\'t ban yourself"); return; } } @@ -1406,7 +1416,7 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1) { if ((((CServer *)pUser)->m_aClients[ClientId1].m_Authed > 0) && ((CServer *)pUser)->m_aClients[ClientId1].m_Authed <= ((CServer *)pUser)->m_aClients[i].m_Authed) { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban an a player with the higher or same rank!"); + pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can\'t ban a player with higher or same level"); return; } } @@ -1761,7 +1771,7 @@ void CServer::SetRconLevel(int ClientId, int Level) CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(0); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true); - m_aClients[ClientId].m_Authed = Level; + m_aClients[ClientId].m_Authed = 0; } else { diff --git a/src/engine/server/server.h b/src/engine/server/server.h index f9cdbfd52..5eec01eb9 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -109,6 +109,7 @@ public: }; CClient m_aClients[MAX_CLIENTS]; + int m_aPrevStates[MAX_CLIENTS]; CSnapshotDelta m_SnapshotDelta; CSnapshotBuilder m_SnapshotBuilder; @@ -180,8 +181,8 @@ public: struct RconResponseInfo { - CServer *m_Server; - int m_ClientId; + CServer *m_Server; + int m_ClientId; }; void ProcessClientPacket(CNetChunk *pPacket); diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 4b9d6a3b0..9a86254d0 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -22,10 +22,11 @@ enum CFGFLAG_CLIENT=2, CFGFLAG_SERVER=4, CFGFLAG_STORE=8, + CFGFLAG_MASTER=16, //DDRace - CMDFLAG_CHEAT=16, - CMDFLAG_TIMER=32, - CMDFLAG_HELPERCMD=64 + CMDFLAG_CHEAT=32, + CMDFLAG_TIMER=64, + CMDFLAG_HELPERCMD=128 }; #endif diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index b8b1492b3..a5bd5bc39 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -39,7 +39,7 @@ MACRO_CONFIG_INT(BrFilterCompatversion, br_filter_compatversion, 1, 0, 1, CFGFLA MACRO_CONFIG_INT(BrSort, br_sort, 0, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "", -1) MACRO_CONFIG_INT(BrSortOrder, br_sort_order, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "", -1) -MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser", -1) +MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 25, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Number of requests to use when refreshing server browser", -1) MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size", -1) MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate", -1) @@ -108,6 +108,7 @@ MACRO_CONFIG_INT(SvServerTest, sv_server_test, 1, 0, 1, CFGFLAG_SERVER, "Whether #endif MACRO_CONFIG_INT(SvCheats, sv_cheats, 0, 0, 1, CFGFLAG_SERVER, "Turns cheats on/off", 4) +MACRO_CONFIG_INT(SvFreezeDelay, sv_freeze_delay, 3, 1, 30, CFGFLAG_SERVER, "How many seconds the players will remain frozen (applies to all except delayed freeze in switch layer & deepfreeze)", 4) MACRO_CONFIG_INT(ClDDRaceCheats, cl_race_cheats, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "",0) MACRO_CONFIG_INT(SvCheatTime, sv_cheattime, 0, 0, 1, CFGFLAG_SERVER, "Whether the time of players will be stopped on cheating or not", 4) MACRO_CONFIG_INT(SvEndlessSuperHook, sv_endless_super_hook, 0, 0, 1, CFGFLAG_SERVER, "Endless hook for super players on/off", 4) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 9f174e466..1cf8cce6c 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -264,7 +264,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client { while(pStr && *pStr) { - CResult *pResult = new(&m_ExecutionQueue.m_pLast->m_Result) CResult; + CResult Result; const char *pEnd = pStr; const char *pNextPart = 0; int InString = 0; @@ -292,24 +292,24 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client pEnd++; } - if(ParseStart(pResult, pStr, (pEnd-pStr) + 1) != 0) + if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0) return; - CCommand *pCommand = FindCommand(pResult->m_pCommand, m_FlagMask); + CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask); if(pCommand) { int IsStrokeCommand = 0; - if(pResult->m_pCommand[0] == '+') + if(Result.m_pCommand[0] == '+') { // insert the stroke direction token - pResult->AddArgument(m_paStrokeStr[Stroke]); + Result.AddArgument(m_paStrokeStr[Stroke]); IsStrokeCommand = 1; } if(Stroke || IsStrokeCommand) { - if(ParseArgs(pResult, pCommand->m_pParams)) + if(ParseArgs(&Result, pCommand->m_pParams)) { RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); 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) { + m_ExecutionQueue.AddEntry(); m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback; m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData; - m_ExecutionQueue.AddEntry(); + m_ExecutionQueue.m_pLast->m_Result = Result; } else { - if(pResult->GetVictim() == CResult::VICTIM_ME) - pResult->SetVictim(ClientId); + if(Result.GetVictim() == CResult::VICTIM_ME) + Result.SetVictim(ClientId); 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(); } - 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); 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 { - 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++) { if (ClientOnline(i) && CompareClients(ClientLevel, i)) { - pResult->SetVictim(i); + Result.SetVictim(i); RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); - pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); + pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId); ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintCallback(); @@ -390,13 +391,13 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client } else { - if (!ClientOnline(pResult->GetVictim())) + if (!ClientOnline(Result.GetVictim())) { RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); PrintResponse(OUTPUT_LEVEL_STANDARD, "Console", "client is offline"); ReleaseAlternativePrintResponseCallback(); } - else if (!CompareClients(ClientLevel, pResult->GetVictim()) && ClientId != pResult->GetVictim()) + else if (!CompareClients(ClientLevel, Result.GetVictim()) && ClientId != Result.GetVictim()) { RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); 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); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); - pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); + pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId); ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintCallback(); @@ -419,7 +420,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client RegisterAlternativePrintCallback(pfnAlternativePrintCallback, pUserData); RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); - pCommand->m_pfnCallback(pResult, pCommand->m_pUserData, ClientId); + pCommand->m_pfnCallback(&Result, pCommand->m_pUserData, ClientId); ReleaseAlternativePrintResponseCallback(); ReleaseAlternativePrintCallback(); @@ -433,7 +434,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, const int Client RegisterAlternativePrintResponseCallback(pfnAlternativePrintResponseCallback, pResponseUserData); 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); ReleaseAlternativePrintResponseCallback(); @@ -762,7 +763,7 @@ void CConsole::StoreCommands(bool Store, int ClientId) { 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); m_ExecutionQueue.Reset(); } diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index 8807b8fe6..f0815c224 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -6,6 +6,9 @@ #include #include "memheap.h" + +#include + class CConsole : public IConsole { class CCommand : public CCommandInfo @@ -81,6 +84,29 @@ class CConsole : public IConsole const char *m_pCommand; 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 { @@ -127,14 +153,17 @@ class CConsole : public IConsole { CQueueEntry *pEntry = static_cast(m_Queue.Allocate(sizeof(CQueueEntry))); 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; + (void)new(&(pEntry->m_Result)) CResult; } void Reset() { m_Queue.Reset(); - m_pFirst = m_pLast = static_cast(m_Queue.Allocate(sizeof(CQueueEntry))); - m_pLast->m_pNext = 0; + m_pFirst = m_pLast = 0; } } m_ExecutionQueue; diff --git a/src/engine/shared/linereader.cpp b/src/engine/shared/linereader.cpp index 3efddb592..b705ff0ec 100644 --- a/src/engine/shared/linereader.cpp +++ b/src/engine/shared/linereader.cpp @@ -4,7 +4,7 @@ void CLineReader::Init(IOHANDLE io) { - m_BufferMaxSize = 4*1024; + m_BufferMaxSize = sizeof(m_aBuffer); m_BufferSize = 0; m_BufferPos = 0; m_IO = io; @@ -13,6 +13,7 @@ void CLineReader::Init(IOHANDLE io) char *CLineReader::Get() { unsigned LineStart = m_BufferPos; + bool CRLFBreak = false; while(1) { @@ -53,10 +54,25 @@ char *CLineReader::Get() if(m_aBuffer[m_BufferPos] == '\n' || m_aBuffer[m_BufferPos] == '\r') { // line found - if(m_aBuffer[m_BufferPos] == '\r' && m_BufferPos+1 < m_BufferSize && m_aBuffer[m_BufferPos+1] == '\n') + if(m_aBuffer[m_BufferPos] == '\r') + { + if(m_BufferPos+1 >= m_BufferSize) + { + // read more to get the connected '\n' + CRLFBreak = true; + ++m_BufferPos; + continue; + } + else if(m_aBuffer[m_BufferPos+1] == '\n') + m_aBuffer[m_BufferPos++] = 0; + } + m_aBuffer[m_BufferPos++] = 0; + return &m_aBuffer[LineStart]; + } + else if(CRLFBreak) + { + if(m_aBuffer[m_BufferPos] == '\n') m_aBuffer[m_BufferPos++] = 0; - m_aBuffer[m_BufferPos] = 0; - m_BufferPos++; return &m_aBuffer[LineStart]; } else diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index ac16a6f8e..7ead43201 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -80,7 +80,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot) for(int i = 0; i < pSnapshot->NumItems(); i++) { int Key = pSnapshot->GetItem(i)->Key(); - int HashID = ((Key>>8)&0xf0) | (Key&0xf); + int HashID = ((Key>>12)&0xf0) | (Key&0xf); if(pHashlist[HashID].m_Num != 64) { pHashlist[HashID].m_aIndex[pHashlist[HashID].m_Num] = i; @@ -92,7 +92,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot) static int GetItemIndexHashed(int Key, const CItemList *pHashlist) { - int HashID = ((Key>>8)&0xf0) | (Key&0xf); + int HashID = ((Key>>12)&0xf0) | (Key&0xf); for(int i = 0; i < pHashlist[HashID].m_Num; i++) { if(pHashlist[HashID].m_aKeys[i] == Key) @@ -523,6 +523,14 @@ int CSnapshotBuilder::Finish(void *SpnapData) void *CSnapshotBuilder::NewItem(int Type, int ID, int Size) { + if(m_DataSize + sizeof(CSnapshotItem) + Size >= CSnapshot::MAX_SIZE || + m_NumItems+1 >= MAX_ITEMS) + { + dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data"); + dbg_assert(m_NumItems < MAX_ITEMS, "too many items"); + return 0; + } + CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize); mem_zero(pObj, sizeof(CSnapshotItem) + Size); @@ -530,9 +538,6 @@ void *CSnapshotBuilder::NewItem(int Type, int ID, int Size) m_aOffsets[m_NumItems] = m_DataSize; m_DataSize += sizeof(CSnapshotItem) + Size; m_NumItems++; - - dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data"); - dbg_assert(m_NumItems < MAX_ITEMS, "too many items"); return pObj->Data(); } diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index abd25a72f..34c3a5487 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -114,7 +114,7 @@ class CSnapshotBuilder { enum { - MAX_ITEMS = 1024*2 + MAX_ITEMS = 1024 }; char m_aData[CSnapshot::MAX_SIZE]; diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index a4940ed76..17b2d66b6 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -8,6 +8,9 @@ #include +#include +#include + #include "broadcast.h" void CBroadcast::OnReset() @@ -17,13 +20,16 @@ void CBroadcast::OnReset() void CBroadcast::OnRender() { + if(m_pClient->m_pScoreboard->Active() || m_pClient->m_pMotd->IsActive()) + return; + Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); if(time_get() < m_BroadcastTime) { CTextCursor Cursor; 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); } } diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 7f3fa7b6f..6bb05cd5a 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -1,6 +1,8 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + #include #include #include diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 5c6821114..b27d80da4 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 96c8c52a1..0589db054 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -2,6 +2,8 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include +#include + #include #include @@ -32,6 +34,11 @@ void CControls::OnReset() m_InputDirectionRight = 0; } +void CControls::OnRelease() +{ + OnReset(); +} + void CControls::OnPlayerDeath() { m_LastData.m_WantedWeapon = m_InputData.m_WantedWeapon = 0; diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h index 38b3c8ba0..a50318f5a 100644 --- a/src/game/client/components/controls.h +++ b/src/game/client/components/controls.h @@ -19,6 +19,7 @@ public: CControls(); virtual void OnReset(); + virtual void OnRelease(); virtual void OnRender(); virtual void OnMessage(int MsgType, void *pRawMsg); virtual bool OnMouseMove(float x, float y); diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index 9f99d431b..4793b3e26 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -1,5 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + #include #include diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 9c75bccee..388ce47b1 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -62,7 +62,14 @@ void CHud::RenderGameTimer() str_format(Buf, sizeof(Buf), "%02d:%02d.%d", Time/60, Time%60, m_DDRaceTick/10); float FontSize = 10.0f; 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()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } } @@ -79,66 +86,143 @@ void CHud::RenderSuddenDeath() } void CHud::RenderScoreHud() -{ - int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags; - float Whole = 300*Graphics()->ScreenAspect(); - +{ // 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]; - str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed); - 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++) + int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags; + float Whole = 300*Graphics()->ScreenAspect(); + + if(GameFlags&GAMEFLAG_TEAMS) { - // draw box - Graphics()->BlendNormal(); - Graphics()->TextureSet(-1); - Graphics()->QuadsBegin(); - if(t == 0) - Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f); - else - 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 - 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]) + char aScoreTeam[2][32]; + str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed); + 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(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 box + Graphics()->BlendNormal(); + Graphics()->TextureSet(-1); + Graphics()->QuadsBegin(); + if(t == 0) + Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f); + else + 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 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)); + // draw score + 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 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] = { 0, 0 }; + int i = 0; + for(int t = 0; t < 2 && i < MAX_CLIENTS && m_pClient->m_Snap.m_paInfoByScore[i]; ++i) + { + if(m_pClient->m_Snap.m_paInfoByScore[i]->m_Team != TEAM_SPECTATORS) + { + apPlayerInfo[t] = m_pClient->m_Snap.m_paInfoByScore[i]; + if(apPlayerInfo[t]->m_ClientId == m_pClient->m_Snap.m_LocalCid) + Local = t; + ++t; + } + } + // search local player info if not a spectator, nor within top2 scores + if(Local == -1 && m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) + { + for(; i < MAX_CLIENTS && m_pClient->m_Snap.m_paInfoByScore[i]; ++i) + { + if(m_pClient->m_Snap.m_paInfoByScore[i]->m_Team != TEAM_SPECTATORS) + ++aPos[1]; + 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]; + Local = 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); + } + } } } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 76a072d9e..0ba74b681 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -759,6 +759,14 @@ int CMenus::Render() // some margin around the screen Screen.Margin(10.0f, &Screen); + static bool s_SoundCheck = false; + if(!s_SoundCheck && m_Popup == POPUP_NONE) + { + if(Client()->SoundInitFailed()) + m_Popup = POPUP_SOUNDERROR; + s_SoundCheck = true; + } + if(m_Popup == POPUP_NONE) { // do tab bar @@ -848,6 +856,13 @@ int CMenus::Render() pExtraText = Localize("Are you sure that you want to delete the demo?"); ExtraAlign = -1; } + else if(m_Popup == POPUP_SOUNDERROR) + { + pTitle = Localize("Sound error"); + pExtraText = Localize("The audio device couldn't be initialised."); + pButtonText = Localize("Ok"); + ExtraAlign = -1; + } else if(m_Popup == POPUP_PASSWORD) { pTitle = Localize("Password incorrect"); @@ -1111,6 +1126,10 @@ void CMenus::SetActive(bool Active) m_pClient->OnRelease(); } } + else if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + m_pClient->OnRelease(); + } } void CMenus::OnReset() diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 9c1bfc453..8da539f46 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -97,6 +97,7 @@ class CMenus : public CComponent POPUP_PURE, POPUP_LANGUAGE, POPUP_DELETE_DEMO, + POPUP_SOUNDERROR, POPUP_PASSWORD, POPUP_QUIT, }; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 7f330bd07..87a1d4894 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -148,9 +148,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) if(ScrollNum > 0) { if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) - s_ScrollValue -= 1.0f/ScrollNum; + s_ScrollValue -= 3.0f/ScrollNum; if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) - s_ScrollValue += 1.0f/ScrollNum; + s_ScrollValue += 3.0f/ScrollNum; } else ScrollNum = 0; @@ -464,7 +464,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing); static float Offset = 0.0f; DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), 12.0f, &Offset); - g_Config.m_BrFilterPing = str_toint(aBuf); + g_Config.m_BrFilterPing = clamp(str_toint(aBuf), 0, 999); } View.HSplitBottom(ms_ButtonHeight, &View, &Button); @@ -498,6 +498,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0); // server details + CTextCursor Cursor; const float FontSize = 12.0f; ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails); RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); @@ -545,15 +546,21 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) } 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); - 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]; str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency); 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); 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); - - CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Row.w; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 8d0a54691..c01240d42 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -3,6 +3,8 @@ #include +#include + #include #include #include @@ -130,8 +132,9 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) if(CurrentTick == TotalTicks) { - DemoPlayer()->Pause(); - DemoPlayer()->SetPos(0); + m_pClient->OnReset(); + DemoPlayer()->Pause(); + DemoPlayer()->SetPos(0); } if(m_MenuActive) @@ -160,6 +163,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) static int s_ResetButton = 0; if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button)) { + m_pClient->OnReset(); DemoPlayer()->Pause(); DemoPlayer()->SetPos(0); } @@ -279,9 +283,9 @@ void CMenus::UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, if(Num > 0) { if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) - gs_ListBoxScrollValue -= 1.0f/Num; + gs_ListBoxScrollValue -= 3.0f/Num; if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) - gs_ListBoxScrollValue += 1.0f/Num; + gs_ListBoxScrollValue += 3.0f/Num; if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 41e326eb6..0d68493ad 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -2,6 +2,8 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include +#include + #include #include #include diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index a1779796f..8e85b25fb 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -3,6 +3,7 @@ #include +#include #include #include diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index d1fe2aed0..d3822dd94 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -1,5 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + #include #include #include @@ -121,9 +123,6 @@ void CPlayers::RenderHook( float IntraTick = Client()->IntraGameTick(); - if(Player.m_Health < 0) // dont render dead players - return; - // set size RenderInfo.m_Size = 64.0f; @@ -131,7 +130,7 @@ void CPlayers::RenderHook( // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) { } else @@ -145,9 +144,6 @@ void CPlayers::RenderHook( vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); - if(Prev.m_Health < 0) // Don't flicker from previous position - Position = vec2(Player.m_X, Player.m_Y); - // draw hook if (Prev.m_HookState>0 && Player.m_HookState>0) { @@ -254,9 +250,6 @@ void CPlayers::RenderPlayer( float IntraTick = Client()->IntraGameTick(); - if(Player.m_Health < 0) // dont render dead players - return; - float Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f; //float angle = 0; @@ -292,7 +285,7 @@ void CPlayers::RenderPlayer( // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) { } else @@ -322,9 +315,6 @@ void CPlayers::RenderPlayer( m_pClient->m_pEffects->AirJump(Position); } - if(Prev.m_Health < 0) // Don't flicker from previous position - Position = vec2(Player.m_X, Player.m_Y); - bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1; bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16); bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0); diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 9d1c8c13b..7bf448fdf 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -1,5 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + #include #include #include @@ -53,32 +55,26 @@ void CScoreboard::RenderGoals(float x, float y, float w) Graphics()->QuadsEnd(); // render goals - //y = ystart+h-54; - float tw = 0.0f; if(m_pClient->m_Snap.m_pGameobj) { if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit); - TextRender()->Text(0, x+20.0f, y, 22.0f, aBuf, -1); - tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + TextRender()->Text(0, x, y, 20.0f, aBuf, -1); } if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), Localize("Time limit: %d min"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit); - TextRender()->Text(0, x+220.0f, y, 22.0f, aBuf, -1); - tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + TextRender()->Text(0, x+220.0f, y, 20.0f, aBuf, -1); } if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Round"), m_pClient->m_Snap.m_pGameobj->m_RoundCurrent, m_pClient->m_Snap.m_pGameobj->m_RoundNum); - TextRender()->Text(0, x+450.0f, y, 22.0f, aBuf, -1); - - /*[48c3fd4c][game/scoreboard]: timelimit x:219.428558 - [48c3fd4c][game/scoreboard]: round x:453.142822*/ + float tw = TextRender()->TextWidth(0, 20.0f, aBuf, -1); + TextRender()->Text(0, x+w-tw-20.0f, y, 20.0f, aBuf, -1); } } } @@ -110,7 +106,7 @@ void CScoreboard::RenderSpectators(float x, float y, float w) { if(Count) str_append(aBuffer, ", ", sizeof(aBuffer)); - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) if (g_Config.m_ClShowIds) { char aId[4]; @@ -128,14 +124,17 @@ void CScoreboard::RenderSpectators(float x, float y, float w) void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle) { + if(Team == TEAM_SPECTATORS) + return; + //float ystart = y; - float h = 750.0f; + float h = 740.0f; Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 17.0f); + RenderTools()->DrawRoundRect(x-10.f, y, w, h, 17.0f); Graphics()->QuadsEnd(); // render title @@ -150,64 +149,23 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch float Offset = 80.0f; float DataOffset = 130; float tw = TextRender()->TextWidth(0, 48, pTitle, -1); + TextRender()->Text(0, x+10, y, 48, pTitle, -1); - if(Team == TEAM_SPECTATORS) - { - TextRender()->Text(0, x+w/2-tw/2, y, 48, pTitle, -1); - } - else - { - TextRender()->Text(0, x+10, y, 48, pTitle, -1); - if(str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) - 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); - } - } + if(m_GameType.find("Race") == std::string::npos) + 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; - // 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 TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1); - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) { TextRender()->Text(0, x+125+Offset, y, 24.0f, Localize("Name"), -1); TextRender()->Text(0, x+w-75, y, 24.0f, Localize("Ping"), -1); @@ -224,7 +182,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch float TeeSizeMod = 1.0f; float TeeOffset = 0.0f; - if(NumPlayers > 13) + if(m_pClient->m_Snap.m_aTeamSize[Team] > 13) { FontSize = 30.0f; LineHeight = 40.0f; @@ -233,9 +191,11 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch } // 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 @@ -252,7 +212,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch float FontSizeResize = FontSize; float Width; - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) { const float ScoreWidth = 150.0f; const float PingWidth = 60.0f; @@ -324,7 +284,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch float size = 64.0f; IGraphics::CQuadItem QuadItem; - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) QuadItem = IGraphics::CQuadItem(x+55+DataOffset, y-15, size/2, size); else QuadItem = IGraphics::CQuadItem(x+55, y-15, size/2, size); @@ -335,7 +295,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientId].m_RenderInfo; TeeInfo.m_Size *= TeeSizeMod; - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+50+DataOffset, y+28+TeeOffset)); else RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+TeeOffset)); @@ -370,26 +330,9 @@ void CScoreboard::RenderRecordingNotification(float x) void CScoreboard::OnRender() { - bool DoScoreBoard = false; - - // if we activly wanna look on the scoreboard - if(m_Active) - DoScoreBoard = true; - - if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) - { - // we are not a spectator, check if we are ead - if(!m_pClient->m_Snap.m_pLocalCharacter || m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) - DoScoreBoard = true; - } - - // if we the game is over - if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) - DoScoreBoard = true; - - if(!DoScoreBoard) + if(!Active()) return; - + m_GameType = std::string(m_pServerInfo.m_aGameType); // if the score board is active, then we should clear the motd message aswell if(m_pClient->m_pMotd->IsActive()) m_pClient->m_pMotd->Clear(); @@ -401,16 +344,13 @@ void CScoreboard::OnRender() Graphics()->MapScreen(0, 0, Width, Height); float w; - if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) + if(m_GameType.find("Race") != std::string::npos) w = 750.0f; else w = 650.0f; if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)) - { RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0); - //render_scoreboard(gameobj, 0, 0, -1, 0); - } else { @@ -422,8 +362,8 @@ void CScoreboard::OnRender() else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed) pText = Localize("Blue team wins!"); - float w = TextRender()->TextWidth(0, 92.0f, pText, -1); - TextRender()->Text(0, Width/2-w/2, 45, 92.0f, pText, -1); + float w = TextRender()->TextWidth(0, 86.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")); @@ -437,5 +377,20 @@ void CScoreboard::OnRender() bool CScoreboard::Active() { - return m_Active | (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver); + // if we activly wanna look on the scoreboard + if(m_Active) + return true; + + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) + { + // we are not a spectator, check if we are dead + if(!m_pClient->m_Snap.m_pLocalCharacter) + return true; + } + + // if the game is over + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) + return true; + + return false; } diff --git a/src/game/client/components/scoreboard.h b/src/game/client/components/scoreboard.h index 1586771ab..45e1b5adf 100644 --- a/src/game/client/components/scoreboard.h +++ b/src/game/client/components/scoreboard.h @@ -4,6 +4,7 @@ #define GAME_CLIENT_COMPONENTS_SCOREBOARD_H #include #include +#include class CScoreboard : public CComponent { @@ -16,6 +17,7 @@ class CScoreboard : public CComponent bool m_Active; CServerInfo m_pServerInfo; + std::string m_GameType; public: CScoreboard(); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index f64fa8e40..25a1088af 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -200,6 +200,7 @@ void CGameClient::OnConsoleInit() Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConServerDummy, 0, "Set team of player to team", 0); Console()->Register("set_team_all", "i", CFGFLAG_SERVER, 0, 0, "Set team of all players to team", 0); Console()->Register("addvote", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Add a voting option", 0); + Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConServerDummy, 0, "Clears the voting options", 0); Console()->Register("vote", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Force a vote to yes/no", 0); @@ -404,7 +405,7 @@ void CGameClient::UpdateLocalCharacterPos() { if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pLocalCharacter->m_Health < 0) || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver)) + if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver)) { // don't use predicted } @@ -631,6 +632,12 @@ void CGameClient::OnGameOver() Client()->AutoScreenshot_Start(); } +void CGameClient::OnStartGame() +{ + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + Client()->DemoRecorder_HandleAutoStart(); +} + void CGameClient::OnRconLine(const char *pLine) { m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); @@ -821,6 +828,8 @@ void CGameClient::OnNewSnapshot() m_Snap.m_pGameobj = (CNetObj_Game *)pData; if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0) OnGameOver(); + else if(s_GameOver != 0 && m_Snap.m_pGameobj->m_GameOver == 0) + OnStartGame(); s_GameOver = m_Snap.m_pGameobj->m_GameOver; } else if(Item.m_Type == NETOBJTYPE_FLAG) @@ -846,6 +855,21 @@ void CGameClient::OnNewSnapshot() } else 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; CServerInfo CurrentServerInfo; @@ -996,6 +1020,11 @@ void CGameClient::OnPredict() m_PredictedTick = Client()->PredGameTick(); } +void CGameClient::OnActivateEditor() +{ + OnRelease(); +} + void CGameClient::CClientData::UpdateRenderInfo() { m_RenderInfo = m_SkinInfo; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index c6a487f78..2baf936b2 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -182,11 +182,13 @@ public: virtual void OnMessage(int MsgId, CUnpacker *pUnpacker); virtual void OnNewSnapshot(); virtual void OnPredict(); + virtual void OnActivateEditor(); virtual int OnSnapInput(int *pData); virtual void OnShutdown(); virtual void OnEnterGame(); virtual void OnRconLine(const char *pLine); virtual void OnGameOver(); + virtual void OnStartGame(); virtual const char *GetItemName(int Type); virtual const char *Version(); diff --git a/src/game/collision.cpp b/src/game/collision.cpp index c6e1ee015..fc2698cb4 100644 --- a/src/game/collision.cpp +++ b/src/game/collision.cpp @@ -89,7 +89,7 @@ void CCollision::Init(class CLayers *pLayers) Index = m_pSwitch[i].m_Type; if(Index <= TILE_NPH) { - if(Index >= TILE_SWITCHTIMEDOPEN && Index <= TILE_SWITCHCLOSE) + if(Index >= TILE_FREEZE && Index <= TILE_SWITCHCLOSE) m_pSwitch[i].m_Type = Index; else m_pSwitch[i].m_Type = 0; @@ -119,7 +119,7 @@ void CCollision::Init(class CLayers *pLayers) } // DDRace tiles - if(Index == TILE_THROUGH || (Index >= TILE_FREEZE && Index <= TILE_UNFREEZE) || (Index >= TILE_SWITCHOPEN && Index<=TILE_BOOST) || (Index >= TILE_BEGIN && Index <= TILE_STOPA) || Index == TILE_CP || Index == TILE_CP_F || (Index >= TILE_OLDLASER && Index <= TILE_NPH)) + if(Index == TILE_THROUGH || (Index >= TILE_FREEZE && Index <= TILE_UNFREEZE) || (Index >= TILE_SWITCHOPEN && Index<=TILE_BOOST) || (Index >= TILE_BEGIN && Index <= TILE_STOPA) || Index == TILE_CP || Index == TILE_CP_F || (Index >= TILE_OLDLASER && Index <= TILE_NPH) || (Index >= TILE_EHOOK_START && Index <= TILE_EHOOK_END) || (Index >= TILE_DFREEZE && Index <= TILE_DUNFREEZE)) m_pFront[i].m_Index = Index; } } @@ -145,7 +145,7 @@ void CCollision::Init(class CLayers *pLayers) } // DDRace tiles - if(Index == TILE_THROUGH || (Index >= TILE_FREEZE && Index <= TILE_UNFREEZE) || (Index >= TILE_SWITCHOPEN && Index<=TILE_BOOST) || (Index >= TILE_BEGIN && Index <= TILE_STOPA) || Index == TILE_CP || Index == TILE_CP_F || (Index >= TILE_OLDLASER && Index <= TILE_NPH)) + if(Index == TILE_THROUGH || (Index >= TILE_FREEZE && Index <= TILE_UNFREEZE) || (Index >= TILE_SWITCHOPEN && Index<=TILE_BOOST) || (Index >= TILE_BEGIN && Index <= TILE_STOPA) || Index == TILE_CP || Index == TILE_CP_F || (Index >= TILE_OLDLASER && Index <= TILE_NPH) || (Index >= TILE_EHOOK_START && Index <= TILE_EHOOK_END) || (Index >= TILE_DFREEZE && Index <= TILE_DUNFREEZE)) m_pTiles[i].m_Index = Index; } } @@ -170,10 +170,10 @@ int CCollision::GetTile(int x, int y) int nx = clamp(x/32, 0, m_Width-1); int ny = clamp(y/32, 0, m_Height-1); if(!m_pTiles || ny < 0 || nx < 0) -{ + { //dbg_msg("Collision","Something is terribly wrong, !m_pTiles %d, ny %d, ny %d", !m_pTiles, ny, ny); return 0; -} + } /*dbg_msg("GetTile","m_Index %d",m_pTiles[ny*m_Width+nx].m_Index);//Remove */ if(m_pTiles[ny*m_Width+nx].m_Index == COLFLAG_SOLID || m_pTiles[ny*m_Width+nx].m_Index == (COLFLAG_SOLID|COLFLAG_NOHOOK) @@ -404,14 +404,14 @@ int CCollision::IsSpeedup(int Index) return false; if(m_pSpeedup[Index].m_Force > 0) - return m_pSpeedup[Index].m_Type; + return Index; return 0; } void CCollision::GetSpeedup(int Index, vec2 *Dir, int *Force, int *MaxSpeed) { - if(Index < 0) + if(Index < 0 || !m_pSpeedup) return; vec2 Direction = vec2(1, 0); float Angle = m_pSpeedup[Index].m_Angle * (pi / 180.0f); @@ -429,7 +429,7 @@ int CCollision::IsSwitch(int Index) if(!m_pSwitch) return false; - if(m_pSwitch[Index].m_Type > 0 && m_pSwitch[Index].m_Number > 0) + if(m_pSwitch[Index].m_Type > 0) return m_pSwitch[Index].m_Type; return 0; @@ -457,13 +457,13 @@ int CCollision::GetSwitchDelay(int Index) if(!m_pSwitch) return false; - if(m_pSwitch[Index].m_Type > 0 && m_pSwitch[Index].m_Number > 0) + if(m_pSwitch[Index].m_Type > 0) return m_pSwitch[Index].m_Delay; return 0; } -int CCollision::IsCp(int x, int y, int* Flags) +int CCollision::IsMover(int x, int y, int* Flags) { int nx = clamp(x/32, 0, m_Width-1); int ny = clamp(y/32, 0, m_Height-1); @@ -694,7 +694,7 @@ int CCollision::Entity(int x, int y, int Layer) default: str_format(aBuf,sizeof(aBuf), "Unknown"); } - dbg_msg("CCollision::Entity","Something is VERY wrong with the %s layer please report this at http://DDRace.info, you will need to post the map as well and any steps tht u think may led to this, Please Also Read the News Section every once and a while", aBuf); + dbg_msg("CCollision::Entity","Something is VERY wrong with the %s layer please report this at http://DDRace.info, you will need to post the map as well and any steps that u think may have led to this, Please Also Read the News Section every once and a while", aBuf); return 0; } switch (Layer) diff --git a/src/game/collision.h b/src/game/collision.h index 890694ec4..e5e002b49 100644 --- a/src/game/collision.h +++ b/src/game/collision.h @@ -91,7 +91,7 @@ public: int IsCheckpoint(int Index); int IsFCheckpoint(int Index); - int IsCp(int x, int y, int* Flags); + int IsMover(int x, int y, int* Flags); vec2 CpSpeed(int index, int Flags = 0); diff --git a/src/game/ddracecommands.h b/src/game/ddracecommands.h index dd1996930..a24adefe0 100644 --- a/src/game/ddracecommands.h +++ b/src/game/ddracecommands.h @@ -6,13 +6,13 @@ #define CONSOLE_COMMAND(name, params, flags, callback, userdata, help, level) #endif -CONSOLE_COMMAND("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "Clears the vote list", 4) CONSOLE_COMMAND("kill_pl", "v", CFGFLAG_SERVER, ConKillPlayer, this, "Kills player v and announces the kill", 2) CONSOLE_COMMAND("logout", "v", CFGFLAG_SERVER, ConLogOut, this, "Logs player v out from the console", -1) CONSOLE_COMMAND("helper", "v", CFGFLAG_SERVER, ConSetlvl1, this, "Authenticates player v to the level of 1", 2) CONSOLE_COMMAND("moder", "v", CFGFLAG_SERVER, ConSetlvl2, this, "Authenticates player v to the level of 2", 3) CONSOLE_COMMAND("admin", "v", CFGFLAG_SERVER, ConSetlvl3, this, "Authenticates player v to the level of 3 (CAUTION: Irreversible, once he is an admin you can't remove his status)", 3) CONSOLE_COMMAND("mute", "vi", CFGFLAG_SERVER, ConMute, this, "Mutes player v for i seconds", 2) +CONSOLE_COMMAND("unmute", "v", CFGFLAG_SERVER, ConUnmute, this, "Unmutes player v", 2) CONSOLE_COMMAND("invis", "v", CFGFLAG_SERVER|CMDFLAG_CHEAT|CMDFLAG_HELPERCMD, ConInvis, this, "Makes player v invisible", 2) CONSOLE_COMMAND("vis", "v", CFGFLAG_SERVER|CMDFLAG_CHEAT|CMDFLAG_HELPERCMD, ConVis, this, "Makes player v visible again", 2) CONSOLE_COMMAND("timerstop", "v", CFGFLAG_SERVER|CMDFLAG_TIMER, ConTimerStop, this, "Stops the timer of player v", 2) diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp index 5e3da93df..84f7b83a7 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/ed_editor.cpp @@ -3,6 +3,8 @@ #include +#include + #include #include #include diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/ed_io.cpp index 03c56305b..b4f4fc438 100644 --- a/src/game/editor/ed_io.cpp +++ b/src/game/editor/ed_io.cpp @@ -1,5 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + #include #include #include diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp index fd1342329..02b7d38be 100644 --- a/src/game/editor/ed_layer_tiles.cpp +++ b/src/game/editor/ed_layer_tiles.cpp @@ -1101,7 +1101,7 @@ void CLayerSwitch::BrushDraw(CLayer *pBrush, float wx, float wy) if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height) continue; - if((l->m_pTiles[y*l->m_Width+x].m_Index >= (ENTITY_ARMOR_1 + ENTITY_OFFSET) && l->m_pTiles[y*l->m_Width+x].m_Index <= (ENTITY_DOOR + ENTITY_OFFSET)) || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHOPEN || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHCLOSE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHTIMEDOPEN || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHTIMEDCLOSE) + if((l->m_pTiles[y*l->m_Width+x].m_Index >= (ENTITY_ARMOR_1 + ENTITY_OFFSET) && l->m_pTiles[y*l->m_Width+x].m_Index <= (ENTITY_DOOR + ENTITY_OFFSET)) || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHOPEN || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHCLOSE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHTIMEDOPEN || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_SWITCHTIMEDCLOSE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_FREEZE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_DFREEZE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_DUNFREEZE) { if(m_pEditor->m_SwitchNum != l->m_SwitchNumber || m_pEditor->m_SwitchDelay != l->m_SwitchDelay) { @@ -1143,6 +1143,17 @@ void CLayerSwitch::BrushDraw(CLayer *pBrush, float wx, float wy) m_pSwitchTile[fy*m_Width+fx].m_Delay = 0; m_pTiles[fy*m_Width+fx].m_Index = 0; } + + if(l->m_pTiles[y*l->m_Width+x].m_Index == TILE_FREEZE) + { + m_pSwitchTile[fy*m_Width+fx].m_Number = 0; + m_pSwitchTile[fy*m_Width+fx].m_Flags = 0; + } + else if(l->m_pTiles[y*l->m_Width+x].m_Index == TILE_DFREEZE || l->m_pTiles[y*l->m_Width+x].m_Index == TILE_DUNFREEZE) + { + m_pSwitchTile[fy*m_Width+fx].m_Flags = 0; + m_pSwitchTile[fy*m_Width+fx].m_Delay = 0; + } } } diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index 5a23f3bae..0f5c0307b 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -362,18 +362,19 @@ void CCharacterCore::Tick(bool UseInput) // handle player <-> player collision float d = distance(m_Pos, p->m_Pos); vec2 Dir = normalize(m_Pos - p->m_Pos); - if (m_pWorld->m_Tuning.m_PlayerCollision) { - + if (m_pWorld->m_Tuning.m_PlayerCollision) + { if(d < PhysSize*1.25f && d > 1.0f) { float a = (PhysSize*1.45f - d); - + float v = 0.5f; // make sure that we don't add excess force by checking the - // direction against the current velocity - vec2 VelDir = normalize(m_Vel); - float v = 1-(dot(VelDir, Dir)+1)/2; - m_Vel = m_Vel + Dir*a*(v*0.75f); - m_Vel = m_Vel * 0.85f; + // direction against the current velocity. if not zero. + if (length(m_Vel) > 0.0001) + v = 1-(dot(normalize(m_Vel), Dir)+1)/2; + + m_Vel += Dir*a*(v*0.75f); + m_Vel *= 0.85f; } } // handle hook influence diff --git a/src/game/localization.cpp b/src/game/localization.cpp index 47b9fddbe..ad025100a 100644 --- a/src/game/localization.cpp +++ b/src/game/localization.cpp @@ -91,6 +91,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon pReplacement += 3; AddString(pLine, pReplacement); } + io_close(IoHandle); m_CurrentVersion = ++m_VersionCounter; return true; diff --git a/src/game/mapitems.h b/src/game/mapitems.h index 74126e4cc..674bd40e8 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -90,6 +90,10 @@ enum TILE_FREEZE = 9, TILE_TELEINEVIL, TILE_UNFREEZE, + TILE_DFREEZE, + TILE_DUNFREEZE, + TILE_EHOOK_START = 17, + TILE_EHOOK_END, //Switches TILE_SWITCHTIMEDOPEN = 22, TILE_SWITCHTIMEDCLOSE, diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index e81cc3ddd..d605ac7be 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -5,20 +5,6 @@ #include #include -void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData, int ClientID) -{ - CGameContext *pSelf = (CGameContext *)pUserData; - - pSelf->m_pVoteOptionHeap->Reset(); - pSelf->m_pVoteOptionFirst = 0; - pSelf->m_pVoteOptionLast = 0; - - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "cleared vote options"); - - CNetMsg_Sv_VoteClearOptions ClearOptionsMsg; - pSelf->Server()->SendPackMsg(&ClearOptionsMsg, MSGFLAG_VITAL, -1); -} - void CGameContext::ConGoLeft(IConsole::IResult *pResult, void *pUserData, int ClientId) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -78,14 +64,46 @@ void CGameContext::ConMute(IConsole::IResult *pResult, void *pUserData, int Clie if(Seconds < 10) Seconds = 10; - if(pSelf->m_apPlayers[Victim]->m_Muted < Seconds * pSelf->Server()->TickSpeed()) - { + if(Victim == ClientId) { + pSelf->SendChatTarget(ClientId, "You can\'t mute yourself"); + } + else { + /*pSelf->m_apPlayers[Victim]->m_Muted = Seconds * pSelf->Server()->TickSpeed(); + str_format(buf, sizeof(buf), "You have been muted by for %d seconds", pSelf->Server()->ClientName(Victim), Seconds); + pSelf->SendChatTarget(Victim, buf);*/ + pSelf->m_apPlayers[Victim]->m_Muted = Seconds * pSelf->Server()->TickSpeed(); str_format(buf, sizeof(buf), "%s muted by %s for %d seconds", pSelf->Server()->ClientName(Victim), pSelf->Server()->ClientName(ClientId), Seconds); pSelf->SendChat(-1, CGameContext::CHAT_ALL, buf); } } +void CGameContext::ConUnmute(IConsole::IResult *pResult, void *pUserData, int ClientId) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + int Victim = pResult->GetVictim(); + char buf[512]; + + if(Victim == ClientId) { + pSelf->SendChatTarget(ClientId, "You can\'t unmute yourself"); + } + else { + if(pSelf->m_apPlayers[Victim]->m_Muted > 0) + { + pSelf->m_apPlayers[Victim]->m_Muted = 0; + str_format(buf, sizeof(buf), "You have been unmuted", pSelf->Server()->ClientName(Victim)); + pSelf->SendChatTarget(Victim, buf); + } + + /*if(pSelf->m_apPlayers[Victim]->m_Muted > 0) + { + pSelf->m_apPlayers[Victim]->m_Muted = 0; + str_format(buf, sizeof(buf), "%s has been unmuted", pSelf->Server()->ClientName(Victim)); + pSelf->SendChat(-1, CGameContext::CHAT_ALL, buf); + }*/ + } +} + void CGameContext::ConSetlvl3(IConsole::IResult *pResult, void *pUserData, int ClientId) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -423,24 +441,32 @@ void CGameContext::ConTimerReStart(IConsole::IResult *pResult, void *pUserData, void CGameContext::ConFreeze(IConsole::IResult *pResult, void *pUserData, int ClientId) { CGameContext *pSelf = (CGameContext *)pUserData; - int time=-1; + int Seconds = -1; int Victim = pResult->GetVictim(); char buf[128]; - if(pResult->NumArguments() >= 1) - time = clamp(pResult->GetInteger(1), -1, 29999); + if(pResult->NumArguments()) + Seconds = clamp(pResult->GetInteger(0), -2, 9999); - CCharacter* chr = pSelf->GetPlayerChar(Victim); - if(!chr) + CCharacter* pChr = pSelf->GetPlayerChar(Victim); + if(!pChr) return; if(pSelf->m_apPlayers[Victim]) { - chr->Freeze(((time!=0&&time!=-1)?(pSelf->Server()->TickSpeed()*time):(-1))); - chr->m_pPlayer->m_RconFreeze = true; + pChr->Freeze(Seconds); + pChr->m_pPlayer->m_RconFreeze = Seconds != -2; CServer* pServ = (CServer*)pSelf->Server(); - str_format(buf, sizeof(buf), "'%s' ClientId=%d has been Frozen.", pServ->ClientName(ClientId), Victim); + if(Seconds >= 0) + str_format(buf, sizeof(buf), "'%s' ClientId=%d has been Frozen for %d.", pServ->ClientName(ClientId), Victim, Seconds); + else if(Seconds == -2) + { + pChr->m_DeepFreeze = true; + str_format(buf, sizeof(buf), "'%s' ClientId=%d has been Deep Frozen.", pServ->ClientName(ClientId), Victim); + } + else + str_format(buf, sizeof(buf), "'%s' ClientId=%d is Frozen until you unfreeze him.", pServ->ClientName(ClientId), Victim); pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "info", buf); } @@ -450,13 +476,24 @@ void CGameContext::ConUnFreeze(IConsole::IResult *pResult, void *pUserData, int { CGameContext *pSelf = (CGameContext *)pUserData; int Victim = pResult->GetVictim(); - + static bool Warning = false; char buf[128]; - CCharacter* chr = pSelf->GetPlayerChar(Victim); - if(!chr) + CCharacter* pChr = pSelf->GetPlayerChar(Victim); + if(!pChr) return; - chr->m_FreezeTime=2; - chr->m_pPlayer->m_RconFreeze = false; + if(pChr->m_DeepFreeze && !Warning) + { + pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "warning", "This client is deeply frozen, repeat the command to defrost him."); + Warning = true; + return; + } + if(pChr->m_DeepFreeze && Warning) + { + pChr->m_DeepFreeze = false; + Warning = false; + } + pChr->m_FreezeTime = 2; + pChr->m_pPlayer->m_RconFreeze = false; CServer* pServ = (CServer*)pSelf->Server(); str_format(buf, sizeof(buf), "'%s' ClientId=%d has been defrosted.", pServ->ClientName(ClientId), Victim); pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "info", buf); diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index b78c57057..da82faefa 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -47,7 +47,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS) // Character, "physical" m_pPlayer's part CCharacter::CCharacter(CGameWorld *pWorld) -: CEntity(pWorld, NETOBJTYPE_CHARACTER) +: CEntity(pWorld, CGameWorld::ENTTYPE_CHARACTER) { m_ProximityRadius = ms_PhysSize; m_Health = 0; @@ -95,10 +95,14 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos) if(m_pPlayer->m_RconFreeze) Freeze(-1); GameServer()->m_pController->OnCharacterSpawn(this); - if(GetPlayer()->m_IsUsingDDRaceClient) { + if(GetPlayer()->m_IsUsingDDRaceClient) + { Controller->m_Teams.SendTeamsState(GetPlayer()->GetCID()); } - + if(g_Config.m_SvTeam == 1) + { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Please join a team before you start"); + } m_DefEmote = EMOTE_NORMAL; m_DefEmoteReset = -1; return true; @@ -120,7 +124,7 @@ void CCharacter::SetWeapon(int W) m_LastWeapon = m_ActiveWeapon; m_QueuedWeapon = -1; m_ActiveWeapon = W; - GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH); + GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH, Teams()->TeamMask(Team())); if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS) m_ActiveWeapon = 0; @@ -186,11 +190,11 @@ void CCharacter::HandleNinja() // check if we Hit anything along the way { - CCharacter *aEnts[64]; + CCharacter *aEnts[MAX_CLIENTS]; vec2 Dir = m_Pos - OldPos; float Radius = m_ProximityRadius * 2.0f; 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**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { @@ -212,7 +216,7 @@ void CCharacter::HandleNinja() continue; // Hit a m_pPlayer, give him damage and stuffs... - GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); + GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT, Teams()->TeamMask(Team())); // set his velocity to fast upward (for now) if(m_NumObjectsHit < 10) m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; @@ -313,7 +317,7 @@ void CCharacter::FireWeapon() if(m_PainSoundTimer<=0) { m_PainSoundTimer = 1 * Server()->TickSpeed(); - GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG); + GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG, Teams()->TeamMask(Team())); } return; } @@ -329,39 +333,43 @@ void CCharacter::FireWeapon() if (!g_Config.m_SvHit) break; - CCharacter *aEnts[64]; + CCharacter *apEnts[MAX_CLIENTS]; int Hits = 0; - int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)aEnts, - 64, NETOBJTYPE_CHARACTER); + int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, + MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); 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 - 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; // set his velocity to fast upward (for now) - 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); - + if(length(pTarget->m_Pos-ProjStartPos) > 0.0f) + GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f, Teams()->TeamMask(Team())); + else + GameServer()->CreateHammerHit(ProjStartPos, Teams()->TeamMask(Team())); + vec2 Dir; - if (length(Target->m_Pos - m_Pos) > 0.0f) - Dir = normalize(Target->m_Pos - m_Pos); + if (length(pTarget->m_Pos - m_Pos) > 0.0f) + Dir = normalize(pTarget->m_Pos - m_Pos); else 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); - 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))) + + vec2 Temp = pTarget->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f * (m_HammerType + 1); + 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; - 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; - 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; - 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; - Target->m_Core.m_Vel = Temp; - Target->UnFreeze(); + Temp -= pTarget->m_Core.m_Vel; + pTarget->TakeDamage(vec2(0.f, -1.f) + Temp, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, + m_pPlayer->GetCID(), m_ActiveWeapon); + pTarget->UnFreeze(); Hits++; } @@ -373,7 +381,7 @@ void CCharacter::FireWeapon() case WEAPON_GUN: { - CProjectile *Proj = new CProjectile + CProjectile *pProj = new CProjectile ( GameWorld(), WEAPON_GUN,//Type @@ -390,7 +398,7 @@ void CCharacter::FireWeapon() // pack the Projectile and send it to the client Directly CNetObj_Projectile p; - Proj->FillInfo(&p); + pProj->FillInfo(&p); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); @@ -405,7 +413,7 @@ void CCharacter::FireWeapon() case WEAPON_SHOTGUN: { new CLaser(&GameServer()->m_World, m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID(), 1); - GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE); + GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE, Teams()->TeamMask(Team())); /*int ShotSpread = 2; CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); @@ -418,7 +426,7 @@ void CCharacter::FireWeapon() a += Spreading[i+2]; float v = 1-(absolute(i)/(float)ShotSpread); float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v); - CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, + CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, m_pPlayer->GetCID(), ProjStartPos, vec2(cosf(a), sinf(a))*Speed, @@ -427,7 +435,7 @@ void CCharacter::FireWeapon() // pack the Projectile and send it to the client Directly CNetObj_Projectile p; - Proj->FillInfo(&p); + pProj->FillInfo(&p); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); @@ -440,7 +448,7 @@ void CCharacter::FireWeapon() case WEAPON_GRENADE: { - CProjectile *Proj = new CProjectile + CProjectile *pProj = new CProjectile ( GameWorld(), WEAPON_GRENADE,//Type @@ -457,7 +465,7 @@ void CCharacter::FireWeapon() // pack the Projectile and send it to the client Directly CNetObj_Projectile p; - Proj->FillInfo(&p); + pProj->FillInfo(&p); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); @@ -557,7 +565,7 @@ bool CCharacter::GiveWeapon(int Weapon, int Ammo) void CCharacter::GiveNinja() { if(!m_aWeapons[WEAPON_NINJA].m_Got) - GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA); + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA, Teams()->TeamMask(Team())); m_Ninja.m_ActivationTick = Server()->Tick(); m_aWeapons[WEAPON_NINJA].m_Got = true; if (!m_FreezeTime) m_aWeapons[WEAPON_NINJA].m_Ammo = -1; @@ -731,8 +739,6 @@ void CCharacter::HandleFly() void CCharacter::Tick() { - std::list < int > Indices = GameServer()->Collision()->GetMapIndices(m_PrevPos, m_Pos); - //dbg_msg("Indices","%d",Indices.size()); /*if(m_pPlayer->m_ForceBalanced) { char Buf[128]; @@ -741,7 +747,7 @@ void CCharacter::Tick() m_pPlayer->m_ForceBalanced = false; }*/ - m_Armor=(m_FreezeTime != -1)?10-(m_FreezeTime/15):0; + m_Armor=(m_FreezeTime >= 0)?10-(m_FreezeTime/15):0; if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0) m_LastMove = Server()->Tick(); @@ -749,9 +755,9 @@ void CCharacter::Tick() { if (m_FreezeTime % Server()->TickSpeed() == 0 || m_FreezeTime == -1) { - GameServer()->CreateDamageInd(m_Pos, 0, m_FreezeTime / Server()->TickSpeed()); + GameServer()->CreateDamageInd(m_Pos, 0, m_FreezeTime / Server()->TickSpeed(), Teams()->TeamMask(Team())); } - if(m_FreezeTime != -1) + if(m_FreezeTime > 0) m_FreezeTime--; else m_Ninja.m_ActivationTick = Server()->Tick(); @@ -760,13 +766,15 @@ void CCharacter::Tick() m_Input.m_Hook = 0; //m_Input.m_Fire = 0; - if (m_FreezeTime == 1) { + if (m_FreezeTime == 1) + { UnFreeze(); + m_pPlayer->m_RconFreeze = false; } } m_Core.m_Input = m_Input; - m_Core.Tick(true); m_Core.m_Id = GetPlayer()->GetCID(); + m_Core.Tick(true); if (m_DefEmoteReset >= 0 && m_DefEmoteReset <= Server()->Tick()) { @@ -774,16 +782,15 @@ void CCharacter::Tick() m_EmoteType = m_DefEmote = EMOTE_NORMAL; m_EmoteStop = -1; } - + m_DoSplash = false; - if (g_Config.m_SvEndlessDrag) + if (g_Config.m_SvEndlessDrag || m_EndlessHook || (m_Super && g_Config.m_SvEndlessSuperHook)) m_Core.m_HookTick = 0; + if (m_DeepFreeze && !m_Super) + Freeze(); if (m_Super && m_Core.m_Jumped > 1) m_Core.m_Jumped = 1; - if (m_Super && g_Config.m_SvEndlessSuperHook) - m_Core.m_HookTick = 0; - /*dbg_msg("character","m_TileIndex=%d , m_TileFIndex=%d",m_TileIndex,m_TileFIndex); //REMOVE*/ - //DDRace + char aBroadcast[128]; m_Time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed()); CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID()); @@ -840,20 +847,86 @@ void CCharacter::Tick() } m_RefreshTime = Server()->Tick(); } -//int num =0; + + // handle tiles + int CurrentIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos); + std::list < int > Indices = GameServer()->Collision()->GetMapIndices(m_PrevPos, m_Pos); if(!Indices.empty()) for(std::list < int >::iterator i = Indices.begin(); i != Indices.end(); i++) HandleTiles(*i); else - HandleTiles(GameServer()->Collision()->GetPureMapIndex(m_Pos)); - - // kill player when leaving gamelayer - if((int)m_Pos.x/32 < -200 || (int)m_Pos.x/32 > GameServer()->Collision()->GetWidth()+200 || - (int)m_Pos.y/32 < -200 || (int)m_Pos.y/32 > GameServer()->Collision()->GetHeight()+200) + HandleTiles(CurrentIndex); + // handle speedup tiles + if(GameServer()->Collision()->IsSpeedup(CurrentIndex)) { - Die(m_pPlayer->GetCID(), WEAPON_WORLD); - } + vec2 Direction, MaxVel, TempVel = m_Core.m_Vel; + int Force, MaxSpeed = 0; + float TeeAngle, SpeederAngle, DiffAngle, SpeedLeft, TeeSpeed; + GameServer()->Collision()->GetSpeedup(CurrentIndex, &Direction, &Force, &MaxSpeed); + if(Force == 255 && MaxSpeed) + { + m_Core.m_Vel = Direction * (MaxSpeed/5); + } + else + { + if(MaxSpeed > 0 && MaxSpeed < 5) MaxSpeed = 5; + //dbg_msg("speedup tile start","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed); + if(MaxSpeed > 0) + { + if(Direction.x > 0.0000001f) + SpeederAngle = -atan(Direction.y / Direction.x); + else if(Direction.x < 0.0000001f) + SpeederAngle = atan(Direction.y / Direction.x) + 2.0f * asin(1.0f); + else if(Direction.y > 0.0000001f) + SpeederAngle = asin(1.0f); + else + SpeederAngle = asin(-1.0f); + if(SpeederAngle < 0) + SpeederAngle = 4.0f * asin(1.0f) + SpeederAngle; + + if(TempVel.x > 0.0000001f) + TeeAngle = -atan(TempVel.y / TempVel.x); + else if(TempVel.x < 0.0000001f) + TeeAngle = atan(TempVel.y / TempVel.x) + 2.0f * asin(1.0f); + else if(TempVel.y > 0.0000001f) + TeeAngle = asin(1.0f); + else + TeeAngle = asin(-1.0f); + + if(TeeAngle < 0) + TeeAngle = 4.0f * asin(1.0f) + TeeAngle; + + TeeSpeed = sqrt(pow(TempVel.x, 2) + pow(TempVel.y, 2)); + + DiffAngle = SpeederAngle - TeeAngle; + SpeedLeft = MaxSpeed / 5.0f - cos(DiffAngle) * TeeSpeed; + + //dbg_msg("speedup tile debug","MaxSpeed %i, TeeSpeed %f, SpeedLeft %f, SpeederAngle %f, TeeAngle %f", MaxSpeed, TeeSpeed, SpeedLeft, SpeederAngle, TeeAngle); + + if(abs(SpeedLeft) > Force && SpeedLeft > 0.0000001f) + TempVel += Direction * Force; + else if(abs(SpeedLeft) > Force) + TempVel += Direction * -Force; + else + TempVel += Direction * SpeedLeft; + } + else + TempVel += Direction * Force; + + if(TempVel.x > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA))) + TempVel.x = 0; + if(TempVel.x < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA))) + TempVel.x = 0; + if(TempVel.y < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA))) + TempVel.y = 0; + if(TempVel.y > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA))) + TempVel.y = 0; + m_Core.m_Vel = TempVel; + //dbg_msg("speedup tile end","(Direction*Force) %f %f m_Core.m_Vel%f %f",(Direction*Force).x,(Direction*Force).y,m_Core.m_Vel.x,m_Core.m_Vel.y); + //dbg_msg("speedup tile end","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed); + } + } // handle Weapons HandleWeapons(); @@ -874,7 +947,7 @@ void CCharacter::HandleTiles(int Index) {//dbg_msg("num","%d",++num); CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController; int MapIndex = Index; - int PureMapIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos); + //int PureMapIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos); float Offset = 4; int MapIndexL = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x + (m_ProximityRadius/2)+Offset,m_Pos.y)); int MapIndexR = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x - (m_ProximityRadius/2)-Offset,m_Pos.y)); @@ -981,8 +1054,8 @@ void CCharacter::HandleTiles(int Index) if(((m_TileIndex == TILE_BEGIN) || (m_TileFIndex == TILE_BEGIN) || FTile1 == TILE_BEGIN || FTile2 == TILE_BEGIN || FTile3 == TILE_BEGIN || FTile4 == TILE_BEGIN || Tile1 == TILE_BEGIN || Tile2 == TILE_BEGIN || Tile3 == TILE_BEGIN || Tile4 == TILE_BEGIN) && (m_DDRaceState == DDRACE_NONE || m_DDRaceState == DDRACE_FINISHED || (m_DDRaceState == DDRACE_STARTED && !Team()))) { bool CanBegin = true; - if(g_Config.m_SvTeam == 1 && (Team() == TEAM_FLOCK || Teams()->Count(Team()) <= 1) ) { - GameServer()->SendChat(-1, GetPlayer()->GetCID(),"I already told you that you must find a friend");//need to make this better + if(g_Config.m_SvTeam == 1 && (Team() == TEAM_FLOCK || Teams()->Count(Team()) <= 1)) { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"I already told you too join a team"); CanBegin = false; } if(CanBegin) { @@ -997,14 +1070,39 @@ void CCharacter::HandleTiles(int Index) { Controller->m_Teams.OnCharacterFinish(m_pPlayer->GetCID()); } - if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Super) + if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Super && !m_DeepFreeze) { - Freeze(Server()->TickSpeed()*3); + Freeze(); } - else if((m_TileIndex == TILE_UNFREEZE) || (m_TileFIndex == TILE_UNFREEZE)) + else if(((m_TileIndex == TILE_UNFREEZE) || (m_TileFIndex == TILE_UNFREEZE)) && !m_DeepFreeze) { UnFreeze(); } + else if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Super && !m_DeepFreeze) + { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You have been deeply frozen"); + m_DeepFreeze = true; + } + else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Super && m_DeepFreeze) + { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You have been thawed from deepfreeze"); + + if((m_TileIndex != TILE_FREEZE) && (m_TileFIndex != TILE_FREEZE)) { + UnFreeze(); + } + + m_DeepFreeze = false; + } + else if(((m_TileIndex == TILE_EHOOK_START) || (m_TileFIndex == TILE_EHOOK_START)) && !m_EndlessHook) + { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Endless hook has been activated"); + m_EndlessHook = true; + } + else if(((m_TileIndex == TILE_EHOOK_END) || (m_TileFIndex == TILE_EHOOK_END)) && m_EndlessHook) + { + GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Endless hook has been deactivated"); + m_EndlessHook = false; + } if(((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA)) && m_Core.m_Vel.x > 0) { if((int)GameServer()->Collision()->GetPos(MapIndexL).x) @@ -1060,86 +1158,18 @@ void CCharacter::HandleTiles(int Index) GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_EndTick[Team()] = 0; GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHCLOSE; } - // handle speedup tiles - if(GameServer()->Collision()->IsSpeedup(PureMapIndex) == TILE_BOOST) + else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER) { - vec2 Direction, MaxVel, TempVel = m_Core.m_Vel; - int Force, MaxSpeed = 0; - float TeeAngle, SpeederAngle, DiffAngle, SpeedLeft, TeeSpeed; - GameServer()->Collision()->GetSpeedup(MapIndex, &Direction, &Force, &MaxSpeed); - if(Force == 255 && MaxSpeed) - { - m_Core.m_Vel = Direction * (MaxSpeed/5); - } - else - { - if(MaxSpeed > 0 && MaxSpeed < 5) MaxSpeed = 5; - //dbg_msg("speedup tile start","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed); - if( - ((Direction.x < 0) && ((int)GameServer()->Collision()->GetPos(MapIndexL).x) && ((int)GameServer()->Collision()->GetPos(MapIndexL).x < (int)m_Core.m_Pos.x)) || - ((Direction.x > 0) && ((int)GameServer()->Collision()->GetPos(MapIndexR).x) && ((int)GameServer()->Collision()->GetPos(MapIndexR).x > (int)m_Core.m_Pos.x)) || - ((Direction.y > 0) && ((int)GameServer()->Collision()->GetPos(MapIndexB).y) && ((int)GameServer()->Collision()->GetPos(MapIndexB).y > (int)m_Core.m_Pos.y)) || - ((Direction.y < 0) && ((int)GameServer()->Collision()->GetPos(MapIndexT).y) && ((int)GameServer()->Collision()->GetPos(MapIndexT).y < (int)m_Core.m_Pos.y)) - ) - m_Core.m_Pos = m_PrevPos; - - if(MaxSpeed > 0) - { - if(Direction.x > 0.0000001f) - SpeederAngle = -atan(Direction.y / Direction.x); - else if(Direction.x < 0.0000001f) - SpeederAngle = atan(Direction.y / Direction.x) + 2.0f * asin(1.0f); - else if(Direction.y > 0.0000001f) - SpeederAngle = asin(1.0f); - else - SpeederAngle = asin(-1.0f); - - if(SpeederAngle < 0) - SpeederAngle = 4.0f * asin(1.0f) + SpeederAngle; - - if(TempVel.x > 0.0000001f) - TeeAngle = -atan(TempVel.y / TempVel.x); - else if(TempVel.x < 0.0000001f) - TeeAngle = atan(TempVel.y / TempVel.x) + 2.0f * asin(1.0f); - else if(TempVel.y > 0.0000001f) - TeeAngle = asin(1.0f); - else - TeeAngle = asin(-1.0f); - - if(TeeAngle < 0) - TeeAngle = 4.0f * asin(1.0f) + TeeAngle; - - TeeSpeed = sqrt(pow(TempVel.x, 2) + pow(TempVel.y, 2)); - - DiffAngle = SpeederAngle - TeeAngle; - SpeedLeft = MaxSpeed / 5.0f - cos(DiffAngle) * TeeSpeed; - - //dbg_msg("speedup tile debug","MaxSpeed %i, TeeSpeed %f, SpeedLeft %f, SpeederAngle %f, TeeAngle %f", MaxSpeed, TeeSpeed, SpeedLeft, SpeederAngle, TeeAngle); - - if(abs(SpeedLeft) > Force && SpeedLeft > 0.0000001f) - TempVel += Direction * Force; - else if(abs(SpeedLeft) > Force) - TempVel += Direction * -Force; - else - TempVel += Direction * SpeedLeft; - } - else - TempVel += Direction * Force; - - if(TempVel.x > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA))) - TempVel.x = 0; - if(TempVel.x < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA))) - TempVel.x = 0; - if(TempVel.y < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA))) - TempVel.y = 0; - if(TempVel.y > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA))) - TempVel.y = 0; - m_Core.m_Vel = TempVel; - //dbg_msg("speedup tile end","(Direction*Force) %f %f m_Core.m_Vel%f %f",(Direction*Force).x,(Direction*Force).y,m_Core.m_Vel.x,m_Core.m_Vel.y); - //dbg_msg("speedup tile end","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed); - } + Freeze(GameServer()->Collision()->GetSwitchDelay(MapIndex)); + } + else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()]) + { + m_DeepFreeze = true; + } + else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()]) + { + m_DeepFreeze = false; } - m_LastBooster = MapIndex; int z = GameServer()->Collision()->IsTeleport(MapIndex); if(z && ((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts[z-1].size()) { @@ -1166,15 +1196,15 @@ void CCharacter::HandleTiles(int Index) m_Core.m_Vel = vec2(0,0); 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 || 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()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || + GameLayerClipped(m_Pos)) && !m_Super) { Die(m_pPlayer->GetCID(), WEAPON_WORLD); @@ -1266,13 +1296,13 @@ void CCharacter::TickDefered() } int Events = m_Core.m_TriggeredEvents; - int Mask = CmaskAllExceptOne(m_pPlayer->GetCID()); + //int Mask = CmaskAllExceptOne(m_pPlayer->GetCID()); - if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask); + if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Teams()->TeamMask(Team())); - if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll()); - if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask); - if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask); + if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, Teams()->TeamMask(Team())); + if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Teams()->TeamMask(Team())); + if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Teams()->TeamMask(Team())); if(m_pPlayer->GetTeam() == TEAM_SPECTATORS) @@ -1301,20 +1331,20 @@ void CCharacter::TickDefered() } } -bool CCharacter::Freeze(int Time) +bool CCharacter::Freeze(int Seconds) { - if ((Time <= 1 || m_Super || m_FreezeTime == -1) && Time != -1) + if ((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * Server()->TickSpeed()) && Seconds != -1) return false; - if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed()) + if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1) { - for(int i=0;iTick(); + m_Armor = 0; + m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed(); + m_FreezeTick = Server()->Tick(); return true; } return false; @@ -1322,28 +1352,12 @@ bool CCharacter::Freeze(int Time) bool CCharacter::Freeze() { - int Time = Server()->TickSpeed()*3; - if (Time <= 1 || m_Super || m_FreezeTime == -1) - return false; - if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed()) - { - for(int i=0;iTick(); - m_FreezeTime=Time; - m_FreezeTick=Server()->Tick(); - return true; - } - return false; + return Freeze(g_Config.m_SvFreezeDelay); } bool CCharacter::UnFreeze() { - if (m_FreezeTime>0) + if (m_FreezeTime > 0) { m_Armor=10; for(int i=0;iSendPackMsg(&Msg, MSGFLAG_VITAL, -1); // a nice sound - GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE); + GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE, Teams()->TeamMask(Team())); // this is for auto respawn after 3 secs m_pPlayer->m_DieTick = Server()->Tick(); diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index c1dc67d49..2f61c7d31 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -122,6 +122,9 @@ public: //DDRace int m_FreezeTime; int m_FreezeTick; + + bool m_DeepFreeze; + bool m_EndlessHook; int m_Doored; @@ -178,7 +181,6 @@ public: int m_StartTime; int m_RefreshTime; - int m_LastBooster; vec2 m_PrevPos; // checkpoints diff --git a/src/game/server/entities/door.cpp b/src/game/server/entities/door.cpp index e1e5141d2..e7e488958 100644 --- a/src/game/server/entities/door.cpp +++ b/src/game/server/entities/door.cpp @@ -6,7 +6,7 @@ #include "door.h" CDoor::CDoor(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length, int Number) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Number = Number; m_Pos = Pos; @@ -30,7 +30,11 @@ void CDoor::ResetCollision() { for(int i=0;iCollision()->SetDCollisionAt(m_Pos.x + (m_Direction.x * i), m_Pos.y + (m_Direction.y * i), TILE_STOPA, 0/*Flags*/, m_Number); + vec2 CurrentPos(m_Pos.x + (m_Direction.x * i), m_Pos.y + (m_Direction.y * i)); + if(GameServer()->Collision()->CheckPoint(CurrentPos) || GameServer()->Collision()->GetTile(m_Pos.x, m_Pos.y) || GameServer()->Collision()->GetFTile(m_Pos.x, m_Pos.y)) + break; + else + GameServer()->Collision()->SetDCollisionAt(m_Pos.x + (m_Direction.x * i), m_Pos.y + (m_Direction.y * i), TILE_STOPA, 0/*Flags*/, m_Number); } } diff --git a/src/game/server/entities/dragger.cpp b/src/game/server/entities/dragger.cpp index 36527af78..78a16d066 100644 --- a/src/game/server/entities/dragger.cpp +++ b/src/game/server/entities/dragger.cpp @@ -12,7 +12,7 @@ const int LENGTH=700; CDragger::CDragger(CGameWorld *pGameWorld, vec2 Pos, float Strength, bool NW, int CatchedTeam, int Layer, int Number) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Layer = Layer; m_Number = Number; @@ -31,7 +31,7 @@ void CDragger::Move() if(m_Target) return; CCharacter *Ents[16]; - int Num = GameServer()->m_World.FindEntities(m_Pos,LENGTH, (CEntity**)Ents, 16, NETOBJTYPE_CHARACTER); + int Num = GameServer()->m_World.FindEntities(m_Pos,LENGTH, (CEntity**)Ents, 16, CGameWorld::ENTTYPE_CHARACTER); int Id=-1; int MinLen=0; for (int i = 0; i < Num; i++) @@ -97,7 +97,7 @@ void CDragger::Tick() { int Flags; m_EvalTick=Server()->Tick(); - int index = GameServer()->Collision()->IsCp(m_Pos.x,m_Pos.y, &Flags); + int index = GameServer()->Collision()->IsMover(m_Pos.x,m_Pos.y, &Flags); if (index) { m_Core=GameServer()->Collision()->CpSpeed(index, Flags); diff --git a/src/game/server/entities/flag.cpp b/src/game/server/entities/flag.cpp index 139bc7446..cff6f10cc 100644 --- a/src/game/server/entities/flag.cpp +++ b/src/game/server/entities/flag.cpp @@ -5,7 +5,7 @@ #include "flag.h" CFlag::CFlag(CGameWorld *pGameWorld, int Team) -: CEntity(pGameWorld, NETOBJTYPE_FLAG) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_FLAG) { m_Team = Team; m_ProximityRadius = ms_PhysSize; diff --git a/src/game/server/entities/gun.cpp b/src/game/server/entities/gun.cpp index 7cd6d9853..1a56d6492 100644 --- a/src/game/server/entities/gun.cpp +++ b/src/game/server/entities/gun.cpp @@ -13,7 +13,7 @@ const int RANGE=700; // CGun ////////////////////////////////////////////////// CGun::CGun(CGameWorld *pGameWorld, vec2 Pos, bool Freeze, bool Explosive, int Layer, int Number) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Layer = Layer; m_Number = Number; @@ -38,7 +38,7 @@ void CGun::Fire() } int Num = -1; - Num = GameServer()->m_World.FindEntities(m_Pos, RANGE, (CEntity**)Ents, 16, NETOBJTYPE_CHARACTER); + Num = GameServer()->m_World.FindEntities(m_Pos, RANGE, (CEntity**)Ents, 16, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; i++) { @@ -77,7 +77,7 @@ void CGun::Tick() { int Flags; m_EvalTick=Server()->Tick(); - int index = GameServer()->Collision()->IsCp(m_Pos.x,m_Pos.y, &Flags); + int index = GameServer()->Collision()->IsMover(m_Pos.x,m_Pos.y, &Flags); if (index) { m_Core=GameServer()->Collision()->CpSpeed(index, Flags); diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 47301660f..f5fc11736 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -6,7 +6,7 @@ #include "laser.h" CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner, int Type) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Pos = Pos; m_Owner = Owner; diff --git a/src/game/server/entities/light.cpp b/src/game/server/entities/light.cpp index f016b2d10..54f1a9e45 100644 --- a/src/game/server/entities/light.cpp +++ b/src/game/server/entities/light.cpp @@ -13,7 +13,7 @@ CLight::CLight(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length, int Layer, int Number) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Layer = Layer; m_Number = Number; @@ -34,7 +34,7 @@ bool CLight::HitCharacter() for(std::list < CCharacter * >::iterator i = HitCharacters.begin(); i != HitCharacters.end(); i++) { CCharacter * Char = *i; if(m_Layer == LAYER_SWITCH && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()]) continue; - Char->Freeze(Server()->TickSpeed()*3); + Char->Freeze(); } return true; } @@ -86,7 +86,7 @@ void CLight::Tick() { int Flags; m_EvalTick=Server()->Tick(); - int index = GameServer()->Collision()->IsCp(m_Pos.x,m_Pos.y, &Flags); + int index = GameServer()->Collision()->IsMover(m_Pos.x,m_Pos.y, &Flags); if (index) { m_Core=GameServer()->Collision()->CpSpeed(index, Flags); diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index a0b7222a7..124668b00 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -5,7 +5,7 @@ #include "pickup.h" CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int Number) -: CEntity(pGameWorld, NETOBJTYPE_PICKUP) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP) { m_Layer = Layer; m_Number = Number; @@ -33,7 +33,7 @@ void CPickup::Move() if (Server()->Tick()%int(Server()->TickSpeed() * 0.15f) == 0) { int Flags; - int index = GameServer()->Collision()->IsCp(m_Pos.x,m_Pos.y, &Flags); + int index = GameServer()->Collision()->IsMover(m_Pos.x,m_Pos.y, &Flags); if (index) { m_Core=GameServer()->Collision()->CpSpeed(index, Flags); @@ -61,7 +61,7 @@ void CPickup::Tick() }*/ // Check if a player intersected us CCharacter *apEnts[MAX_CLIENTS]; - int Num = GameWorld()->FindEntities(m_Pos, 20.0f, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER); + int Num = GameWorld()->FindEntities(m_Pos, 20.0f, (CEntity**)apEnts, 64, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; ++i) { CCharacter * pChr = apEnts[i]; if(pChr && pChr->IsAlive()) @@ -121,16 +121,21 @@ void CPickup::Tick() } break; - case POWERUP_NINJA: + case POWERUP_NINJA: + { + // activate ninja on target player + pChr->GiveNinja(); + //RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; + + /*// loop through all players, setting their emotes + CCharacter *pC = static_cast(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER)); + for(; pC; pC = (CCharacter *)pC->TypeNext()) { - // activate ninja on target player - //if(!pChr->m_FreezeTime) pChr->GiveNinja(); - pChr->GiveNinja(); - //RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; - - break; - } - + if (pC != pChr) + pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed()); + }*/ + break; + } default: break; }; diff --git a/src/game/server/entities/plasma.cpp b/src/game/server/entities/plasma.cpp index 23c3e6859..ac0466033 100644 --- a/src/game/server/entities/plasma.cpp +++ b/src/game/server/entities/plasma.cpp @@ -14,7 +14,7 @@ const float ACCEL=1.1f; ////////////////////////////////////////////////// CPlasma::CPlasma(CGameWorld *pGameWorld, vec2 Pos, vec2 Dir, bool Freeze, bool Explosive, int ResponsibleTeam) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Pos = Pos; m_Core = Dir; @@ -34,7 +34,7 @@ bool CPlasma::HitCharacter() return false; if(Hit->Team() != m_ResponsibleTeam) return false; - m_Freeze ? Hit->Freeze(Server()->TickSpeed()*3) : Hit->UnFreeze(); + m_Freeze ? Hit->Freeze() : Hit->UnFreeze(); if(m_Explosive) GameServer()->CreateExplosion(m_Pos, -1, WEAPON_GRENADE, true, m_ResponsibleTeam, Hit->Teams()->TeamMask(m_ResponsibleTeam)); GameServer()->m_World.DestroyEntity(this); diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index e5737bb03..5a0265bd7 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -22,7 +22,7 @@ CProjectile::CProjectile int Layer, int Number ) -: CEntity(pGameWorld, NETOBJTYPE_PROJECTILE) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE) { m_Layer = Layer; m_Number = Number; @@ -120,7 +120,7 @@ void CProjectile::Tick() { 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))) { @@ -130,7 +130,7 @@ void CProjectile::Tick() (m_Owner != -1)? TeamMask : -1); } else if(TargetChr && m_Freeze && ((m_Layer == LAYER_SWITCH && GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[TargetChr->Team()]) || m_Layer != LAYER_SWITCH)) - TargetChr->Freeze(Server()->TickSpeed()*3); + TargetChr->Freeze(); if(Collide && m_Bouncing != 0) { m_StartTick = Server()->Tick(); diff --git a/src/game/server/entity.cpp b/src/game/server/entity.cpp index 1f37d167d..aff36943c 100644 --- a/src/game/server/entity.cpp +++ b/src/game/server/entity.cpp @@ -11,15 +11,13 @@ CEntity::CEntity(CGameWorld *pGameWorld, int ObjType) { m_pGameWorld = pGameWorld; - m_Objtype = ObjType; + m_ObjType = ObjType; m_Pos = vec2(0,0); m_ProximityRadius = 0; m_MarkedForDestroy = false; m_Id = Server()->SnapNewID(); - m_pNextEntity = 0; - m_pPrevEntity = 0; m_pPrevTypeEntity = 0; m_pNextTypeEntity = 0; } @@ -50,3 +48,9 @@ int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos) return 1; 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; +} diff --git a/src/game/server/entity.h b/src/game/server/entity.h index 3e00991de..ebdd0bf1f 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -57,11 +57,8 @@ class CEntity { MACRO_ALLOC_HEAP() -private: - friend class CGameWorld; // thy these? - CEntity *m_pPrevEntity; - CEntity *m_pNextEntity; + friend class CGameWorld; // entity list handling CEntity *m_pPrevTypeEntity; CEntity *m_pNextTypeEntity; @@ -69,7 +66,7 @@ private: protected: bool m_MarkedForDestroy; int m_Id; - int m_Objtype; + int m_ObjType; int m_Number; int m_Layer; public: @@ -143,7 +140,8 @@ public: */ int NetworkClipped(int SnappingClient); int NetworkClipped(int SnappingClient, vec2 CheckPos); - + + bool GameLayerClipped(vec2 CheckPos); /* Variable: proximity_radius diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 506cf48e4..e859688a9 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -138,10 +138,10 @@ void CGameContext::CreateExplosion(vec2 P, int Owner, int Weapon, bool NoDamage, /*if(!NoDamage) {*/ // deal damage - CCharacter *apEnts[64]; + CCharacter *apEnts[MAX_CLIENTS]; float Radius = 135.0f; float InnerRadius = 48.0f; - int Num = m_World.FindEntities(P, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER); + int Num = m_World.FindEntities(P, Radius, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; i++) { vec2 Diff = apEnts[i]->m_Pos - P; @@ -329,7 +329,7 @@ void CGameContext::SendChat(int ChatterClientId, int Team, const char *pText, in Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i); } } else { - if(Teams->Team(i) == Team) { + if(Teams->Team(i) == Team && m_apPlayers[i]->GetTeam() != CHAT_SPEC) { Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i); } } @@ -647,21 +647,24 @@ void CGameContext::OnClientEnter(int ClientId) Score()->PlayerData(ClientId)->m_CurrentTime = Score()->PlayerData(ClientId)->m_BestTime; m_apPlayers[ClientId]->m_Score = (Score()->PlayerData(ClientId)->m_BestTime)?Score()->PlayerData(ClientId)->m_BestTime:-9999; - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientId), m_pController->GetTeamName(m_apPlayers[ClientId]->GetTeam())); - SendChat(-1, CGameContext::CHAT_ALL, aBuf); - - SendChatTarget(ClientId, "DDRace Mod. Version: " DDRACE_VERSION); - SendChatTarget(ClientId, "Official site: DDRace.info"); - SendChatTarget(ClientId, "For more Info /cmdlist"); - SendChatTarget(ClientId, "Or visit DDRace.info"); - SendChatTarget(ClientId, "To see this again say /info"); - SendChatTarget(ClientId, "Note This is an Alpha release, just for testing, your feedback is important!!"); + if(((CServer *) Server())->m_aPrevStates[ClientId] < CServer::CClient::STATE_INGAME) + { + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientId), m_pController->GetTeamName(m_apPlayers[ClientId]->GetTeam())); + SendChat(-1, CGameContext::CHAT_ALL, aBuf); - if(g_Config.m_SvWelcome[0]!=0) SendChatTarget(ClientId,g_Config.m_SvWelcome); - //str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientId, Server()->ClientName(ClientId), m_apPlayers[ClientId]->GetTeam()); + SendChatTarget(ClientId, "DDRace Mod. Version: " DDRACE_VERSION); + SendChatTarget(ClientId, "Official site: DDRace.info"); + SendChatTarget(ClientId, "For more Info /cmdlist"); + SendChatTarget(ClientId, "Or visit DDRace.info"); + SendChatTarget(ClientId, "To see this again say /info"); + SendChatTarget(ClientId, "Note This is an Alpha release, just for testing, your feedback is important!!"); + + if(g_Config.m_SvWelcome[0]!=0) SendChatTarget(ClientId,g_Config.m_SvWelcome); + //str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientId, Server()->ClientName(ClientId), m_apPlayers[ClientId]->GetTeam()); - Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); + } m_VoteUpdate = true; } @@ -763,7 +766,7 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId) //if(Team) int GameTeam = ((CGameControllerDDRace*)m_pController)->m_Teams.m_Core.Team(p->GetCID()); if(Team) { - Team = (p->GetTeam() == -1) ? CHAT_SPEC : (GameTeam == 0 ? CHAT_ALL : GameTeam); + Team = ((p->GetTeam() == -1) ? CHAT_SPEC : GameTeam); } else { Team = CHAT_ALL; } @@ -844,6 +847,11 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId) { if(str_comp_nocase(pMsg->m_Value, pOption->m_aCommand) == 0) { + if(!Console()->LineIsValid(pOption->m_aCommand)) + { + SendChatTarget(ClientId, "Invalid option"); + return; + } //str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s'", Server()->ClientName(ClientId), pOption->m_aCommand); if(m_apPlayers[ClientId]->m_Authed <= 0 && strncmp(pOption->m_aCommand, "sv_map ", 7) == 0 && time_get() < last_mapvote + (time_freq() * g_Config.m_SvVoteMapTimeDelay)) { @@ -1310,6 +1318,18 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData, int C pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1); } +void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData, int ClientID) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "cleared votes"); + CNetMsg_Sv_VoteClearOptions VoteClearOptionsMsg; + pSelf->Server()->SendPackMsg(&VoteClearOptionsMsg, MSGFLAG_VITAL, -1); + pSelf->m_pVoteOptionHeap->Reset(); + pSelf->m_pVoteOptionFirst = 0; + pSelf->m_pVoteOptionLast = 0; +} + void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData, int ClientID) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -1351,6 +1371,7 @@ void CGameContext::OnConsoleInit() Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, "Sends a server message to all players", 3); Console()->Register("set_team", "vi", CFGFLAG_SERVER, ConSetTeam, this, "Changes the team of player i1 to team i2", 2); Console()->Register("addvote", "r", CFGFLAG_SERVER, ConAddVote, this, "Adds a vote entry to the clients", 4); + Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "", 3); Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Modifies tune parameter s to value i", 4); Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Resets all tuning", 4); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 9a694d025..0fffba3ff 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -56,10 +56,12 @@ class CGameContext : public IGameServer static void ConSetTeam(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConSetTeamAll(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConAddVote(IConsole::IResult *pResult, void *pUserData, int ClientId); + static void ConClearVotes(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConVote(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConMute(IConsole::IResult *pResult, void *pUserData, int ClientId); + static void ConUnmute(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConLogOut(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConSetlvl1(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConSetlvl2(IConsole::IResult *pResult, void *pUserData, int ClientId); @@ -100,7 +102,6 @@ class CGameContext : public IGameServer static void ConMove(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConMoveRaw(IConsole::IResult *pResult, void *pUserData, int ClientId); - static void ConClearVotes(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConInvisMe(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConVisMe(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConInvis(IConsole::IResult *pResult, void *pUserData, int ClientId); @@ -284,4 +285,4 @@ inline int CmaskAll() { return -1; } inline int CmaskOne(int ClientId) { return 1<(GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER)); + CCharacter *pC = static_cast(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER)); for(; pC; pC = (CCharacter *)pC->TypeNext()) { // team mates are not as dangerous as enemies @@ -66,10 +66,7 @@ float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) Scoremod = 0.5f; float d = distance(Pos, pC->m_Pos); - if(d == 0) - Score += 1000000000.0f; - else - Score += 1.0f/d; + Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d); } return Score; @@ -840,7 +837,7 @@ bool IGameController::CheckTeamBalance() char aBuf[256]; if(absolute(aT[0]-aT[1]) >= 2) { - str_format(aBuf, sizeof(aBuf), "Team is NOT balanced (red=%d blue=%d)", aT[0], aT[1]); + str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); if(GameServer()->m_pController->m_UnbalancedTick == -1) GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); @@ -848,7 +845,7 @@ bool IGameController::CheckTeamBalance() } else { - str_format(aBuf, sizeof(aBuf), "Team is balanced (red=%d blue=%d)", aT[0], aT[1]); + str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); GameServer()->m_pController->m_UnbalancedTick = -1; return true; diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp index 5ac201720..7f2a6a94e 100644 --- a/src/game/server/gamemodes/ctf.cpp +++ b/src/game/server/gamemodes/ctf.cpp @@ -92,8 +92,8 @@ void CGameControllerCTF::Tick() if(!F) continue; - // flag hits death-tile, reset it - if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH) + // 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 || F->GameLayerClipped(F->m_Pos)) { GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); F->Reset(); @@ -140,7 +140,7 @@ void CGameControllerCTF::Tick() else { CCharacter *apCloseCCharacters[MAX_CLIENTS]; - int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); + int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; i++) { if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == TEAM_SPECTATORS || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL)) @@ -213,4 +213,4 @@ void CGameControllerCTF::Tick() } } } -*/ \ No newline at end of file +*/ diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 5695b030c..72c712149 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -15,16 +15,16 @@ CGameWorld::CGameWorld() m_Paused = false; m_ResetRequested = false; - m_pFirstEntity = 0x0; - for(int i = 0; i < NUM_ENT_TYPES; i++) + for(int i = 0; i < NUM_ENTTYPES; i++) m_apFirstEntityTypes[i] = 0; } CGameWorld::~CGameWorld() { // delete all entities - while(m_pFirstEntity) - delete m_pFirstEntity; + for(int i = 0; i < NUM_ENTTYPES; i++) + while(m_apFirstEntityTypes[i]) + delete m_apFirstEntityTypes[i]; } void CGameWorld::SetGameServer(CGameContext *pGameServer) @@ -35,15 +35,16 @@ void CGameWorld::SetGameServer(CGameContext *pGameServer) CEntity *CGameWorld::FindFirst(int Type) { - return m_apFirstEntityTypes[Type]; + return Type < 0 || Type >= NUM_ENTTYPES ? 0 : m_apFirstEntityTypes[Type]; } - int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type) { + if(Type < 0 || Type >= NUM_ENTTYPES) + return 0; + int Num = 0; - for(CEntity *pEnt = (Type<0) ? m_pFirstEntity : m_apFirstEntityTypes[Type]; - pEnt; pEnt = (Type<0) ? pEnt->m_pNextEntity : pEnt->m_pNextTypeEntity) + for(CEntity *pEnt = m_apFirstEntityTypes[Type]; pEnt; pEnt = pEnt->m_pNextTypeEntity) { if(distance(pEnt->m_Pos, Pos) < Radius+pEnt->m_ProximityRadius) { @@ -59,26 +60,17 @@ int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, void CGameWorld::InsertEntity(CEntity *pEnt) { - CEntity *pCur = m_pFirstEntity; - while(pCur) - { +#ifdef CONF_DEBUG + for(CEntity *pCur = m_apFirstEntityTypes[pEnt->m_ObjType]; pCur; pCur = pCur->m_pNextTypeEntity) dbg_assert(pCur != pEnt, "err"); - pCur = pCur->m_pNextEntity; - } +#endif // insert it - if(m_pFirstEntity) - m_pFirstEntity->m_pPrevEntity = pEnt; - pEnt->m_pNextEntity = m_pFirstEntity; - pEnt->m_pPrevEntity = 0x0; - m_pFirstEntity = pEnt; - - // into typelist aswell - if(m_apFirstEntityTypes[pEnt->m_Objtype]) - m_apFirstEntityTypes[pEnt->m_Objtype]->m_pPrevTypeEntity = pEnt; - pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_Objtype]; + if(m_apFirstEntityTypes[pEnt->m_ObjType]) + m_apFirstEntityTypes[pEnt->m_ObjType]->m_pPrevTypeEntity = pEnt; + pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_ObjType]; pEnt->m_pPrevTypeEntity = 0x0; - m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt; + m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt; } void CGameWorld::DestroyEntity(CEntity *pEnt) @@ -89,26 +81,21 @@ void CGameWorld::DestroyEntity(CEntity *pEnt) void CGameWorld::RemoveEntity(CEntity *pEnt) { // not in the list - if(!pEnt->m_pNextEntity && !pEnt->m_pPrevEntity && m_pFirstEntity != pEnt) + if(!pEnt->m_pNextTypeEntity && !pEnt->m_pPrevTypeEntity && m_apFirstEntityTypes[pEnt->m_ObjType] != pEnt) return; // remove - if(pEnt->m_pPrevEntity) - pEnt->m_pPrevEntity->m_pNextEntity = pEnt->m_pNextEntity; - else - m_pFirstEntity = pEnt->m_pNextEntity; - if(pEnt->m_pNextEntity) - pEnt->m_pNextEntity->m_pPrevEntity = pEnt->m_pPrevEntity; - if(pEnt->m_pPrevTypeEntity) pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity; else - m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt->m_pNextTypeEntity; + m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt->m_pNextTypeEntity; if(pEnt->m_pNextTypeEntity) pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity; - pEnt->m_pNextEntity = 0; - pEnt->m_pPrevEntity = 0; + // keep list traversing valid + if(m_pNextTraverseEntity == pEnt) + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->m_pNextTypeEntity = 0; pEnt->m_pPrevTypeEntity = 0; } @@ -116,15 +103,25 @@ void CGameWorld::RemoveEntity(CEntity *pEnt) // void CGameWorld::Snap(int SnappingClient) { - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Snap(SnappingClient); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Snap(SnappingClient); + pEnt = m_pNextTraverseEntity; + } } void CGameWorld::Reset() { // reset all entities - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Reset(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Reset(); + pEnt = m_pNextTraverseEntity; + } RemoveEntities(); GameServer()->m_pController->PostReset(); @@ -136,17 +133,17 @@ void CGameWorld::Reset() void CGameWorld::RemoveEntities() { // destroy objects marked for destruction - CEntity *pEnt = m_pFirstEntity; - while(pEnt) - { - CEntity *pNext = pEnt->m_pNextEntity; - if(pEnt->m_MarkedForDestroy) + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) { - RemoveEntity(pEnt); - pEnt->Destroy(); + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + if(pEnt->m_MarkedForDestroy) + { + RemoveEntity(pEnt); + pEnt->Destroy(); + } + pEnt = m_pNextTraverseEntity; } - pEnt = pNext; - } } void CGameWorld::Tick() @@ -159,11 +156,21 @@ void CGameWorld::Tick() if(GameServer()->m_pController->IsForceBalanced()) GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced"); // update all objects - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Tick(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Tick(); + pEnt = m_pNextTraverseEntity; + } - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->TickDefered(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->TickDefered(); + pEnt = m_pNextTraverseEntity; + } } RemoveEntities(); @@ -178,7 +185,7 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v vec2 LineDir = normalize(Pos1-Pos0); CCharacter *pClosest = 0; - CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) @@ -208,7 +215,7 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotTh float ClosestRange = Radius*2; CCharacter *pClosest = 0; - CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) @@ -233,7 +240,7 @@ std::list CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 // Find other players vec2 LineDir = normalize(Pos1-Pos0); - CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)FindFirst(CGameWorld::ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) @@ -252,7 +259,7 @@ std::list CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 void CGameWorld::ReleaseHooked(int ClientId) { - CCharacter *p = (CCharacter *)CGameWorld::FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)CGameWorld::FindFirst(CGameWorld::ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) if(p->m_Core.m_HookedPlayer == ClientId && !p->m_Super) { @@ -261,5 +268,4 @@ void CGameWorld::ReleaseHooked(int ClientId) p->m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT; p->m_Core.m_HookState = HOOK_RETRACTED; } - -} \ No newline at end of file +} diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 142ef4b51..d9b1a9d8f 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -16,17 +16,23 @@ class CCharacter; */ class CGameWorld { +public: + enum + { + ENTTYPE_PROJECTILE = 0, + ENTTYPE_LASER, + ENTTYPE_PICKUP, + ENTTYPE_FLAG, + ENTTYPE_CHARACTER, + NUM_ENTTYPES + }; + +private: void Reset(); void RemoveEntities(); - enum - { - NUM_ENT_TYPES=10, // TODO: are more exact value perhaps? :) - }; - - // TODO: two lists seams kinda not good, shouldn't be needed - CEntity *m_pFirstEntity; - CEntity *m_apFirstEntityTypes[NUM_ENT_TYPES]; + CEntity *m_pNextTraverseEntity; + CEntity *m_apFirstEntityTypes[NUM_ENTTYPES]; class CGameContext *m_pGameServer; class IServer *m_pServer; @@ -44,7 +50,6 @@ public: void SetGameServer(CGameContext *pGameServer); - CEntity *FindFirst() { return m_pFirstEntity; } CEntity *FindFirst(int Type); /* @@ -57,12 +62,12 @@ public: ents - Pointer to a list that should be filled with the pointers to the entities. max - Number of entities that fits into the ents array. - type - Type of the entities to find. -1 for all types. + type - Type of the entities to find. Returns: Number of entities found and added to the ents array. */ - int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type = -1); + int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type); /* Function: InterserctCharacters diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 77d9e0a5e..9b43410ce 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -1,11 +1,9 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include -//#include //TODO:GFX check if linux still needs this +#include #include #include -#include - #include "player.h" #include "gamecontext.h" #include @@ -46,7 +44,9 @@ CPlayer::~CPlayer() void CPlayer::Tick() { - Server()->SetClientAuthed(m_ClientID, m_Authed); +#ifdef CONF_DEBUG + if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies) +#endif if(!Server()->ClientIngame(m_ClientID)) return; @@ -95,6 +95,9 @@ void CPlayer::Tick() void CPlayer::Snap(int SnappingClient) { +#ifdef CONF_DEBUG + if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies) +#endif if(!Server()->ClientIngame(m_ClientID)) return; @@ -240,7 +243,7 @@ void CPlayer::TryRespawn() // check if the position is occupado CEntity *apEnts[2] = {0}; - int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, NETOBJTYPE_CHARACTER); + int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, CGameWorld::ENTTYPE_CHARACTER); if(NumEnts < 3) { m_Spawning = false; @@ -285,6 +288,8 @@ void CPlayer::LoadCharacter() Character->m_LastWeapon = m_PauseInfo.m_LastWeapon; Character->m_HammerType = m_PauseInfo.m_HammerType; Character->m_Super = m_PauseInfo.m_Super; + Character->m_DeepFreeze = m_PauseInfo.m_DeepFreeze; + Character->m_EndlessHook = m_PauseInfo.m_EndlessHook; CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController; Controller->m_Teams.m_Core.Team(GetCID(), m_PauseInfo.m_Team); m_PauseInfo.m_Respawn = false; @@ -315,6 +320,8 @@ void CPlayer::SaveCharacter() m_PauseInfo.m_LastWeapon = Character->m_LastWeapon; m_PauseInfo.m_HammerType = Character->m_HammerType; m_PauseInfo.m_Super = Character->m_Super; + m_PauseInfo.m_DeepFreeze = Character->m_DeepFreeze; + m_PauseInfo.m_EndlessHook = Character->m_EndlessHook; CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController; m_PauseInfo.m_Team = Controller->m_Teams.m_Core.Team(GetCID()); m_PauseInfo.m_PauseTime = Server()->Tick(); diff --git a/src/game/server/player.h b/src/game/server/player.h index 9cead3949..869ef66cf 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -57,6 +57,8 @@ public: bool m_aHasWeapon[NUM_WEAPONS]; int m_HammerType; bool m_Super; + bool m_DeepFreeze; + bool m_EndlessHook; int m_PauseTime; int m_Team; } m_PauseInfo; diff --git a/src/game/server/score/file_score.cpp b/src/game/server/score/file_score.cpp index 70c8c7d54..0a7b28188 100644 --- a/src/game/server/score/file_score.cpp +++ b/src/game/server/score/file_score.cpp @@ -1,5 +1,7 @@ /* copyright (c) 2008 rajh and gregwar. Score stuff */ +#include + #include #include #include diff --git a/src/game/teamscore.h b/src/game/teamscore.h index 24e537375..e8dc68e6f 100644 --- a/src/game/teamscore.h +++ b/src/game/teamscore.h @@ -25,4 +25,4 @@ public: void Reset(); }; -#endif \ No newline at end of file +#endif diff --git a/src/game/variables.h b/src/game/variables.h index 5b8b364c1..fc163e66d 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -25,7 +25,7 @@ MACRO_CONFIG_INT(ClMouseMaxDistance, cl_mouse_max_distance, 800, 0, 0, CFGFLAG_C MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) -MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) +//MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day", -1) diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 743988981..fffc0740f 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -2,6 +2,10 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include #include +#include +#include +#include +#include #include "mastersrv.h" @@ -10,6 +14,7 @@ enum { MAX_SERVERS_PER_PACKET=128, MAX_PACKETS=16, MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS, + MAX_BANS=128, EXPIRE_TIME = 90 }; @@ -60,11 +65,23 @@ struct CCountPacketData static CCountPacketData m_CountData; + +struct CBanEntry +{ + NETADDR m_Address; + int64 m_Expire; +}; + +static CBanEntry m_aBans[MAX_BANS]; +static int m_NumBans = 0; + //static int64 server_expire[MAX_SERVERS]; static CNetClient m_NetChecker; // NAT/FW checker static CNetClient m_NetOp; // main +IConsole *m_pConsole; + void BuildPackets() { CServerEntry *pCurrent = &m_aServers[0]; @@ -237,9 +254,61 @@ void PurgeServers() } } -int main(int argc, char **argv) // ignore_convention +bool CheckBan(NETADDR Addr) { - int64 LastBuild = 0; + for(int i = 0; i < m_NumBans; i++) + { + if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0) + { + return true; + } + } + Addr.port = 0; + for(int i = 0; i < m_NumBans; i++) + { + if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0) + { + return true; + } + } + return false; +} + +void ConAddBan(IConsole::IResult *pResult, void *pUser, int ClientID) +{ + if(m_NumBans == MAX_BANS) + { + dbg_msg("mastersrv", "error: banlist is full"); + return; + } + + net_addr_from_str(&m_aBans[m_NumBans].m_Address, pResult->GetString(0)); + + if(CheckBan(m_aBans[m_NumBans].m_Address)) + { + dbg_msg("mastersrv", "duplicate ban: %d.%d.%d.%d:%d", + m_aBans[m_NumBans].m_Address.ip[0], m_aBans[m_NumBans].m_Address.ip[1], + m_aBans[m_NumBans].m_Address.ip[2], m_aBans[m_NumBans].m_Address.ip[3], + m_aBans[m_NumBans].m_Address.port); + return; + } + + dbg_msg("mastersrv", "ban added: %d.%d.%d.%d:%d", + m_aBans[m_NumBans].m_Address.ip[0], m_aBans[m_NumBans].m_Address.ip[1], + m_aBans[m_NumBans].m_Address.ip[2], m_aBans[m_NumBans].m_Address.ip[3], + m_aBans[m_NumBans].m_Address.port); + m_NumBans++; +} + +void ReloadBans() +{ + m_NumBans = 0; + m_pConsole->ExecuteFile("master.cfg"); +} + +int main(int argc, const char **argv) // ignore_convention +{ + int64 LastBuild = 0, LastBanReload = 0; NETADDR BindAddr; dbg_logger_stdout(); @@ -256,6 +325,17 @@ int main(int argc, char **argv) // ignore_convention //mem_copy(data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)); mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); + + IKernel *pKernel = IKernel::Create(); + IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); + + m_pConsole = CreateConsole(CFGFLAG_MASTER); + m_pConsole->Register("ban", "s", CFGFLAG_MASTER, ConAddBan, 0, "Ban IP from mastersrv", 0); + bool RegisterFail = !pKernel->RegisterInterface(pStorage); + RegisterFail |= !pKernel->RegisterInterface(m_pConsole); + + if(RegisterFail) + return -1; dbg_msg("mastersrv", "started"); @@ -268,6 +348,9 @@ int main(int argc, char **argv) // ignore_convention CNetChunk Packet; while(m_NetOp.Recv(&Packet)) { + // check if the server is banned + if(CheckBan(Packet.m_Address)) continue; + if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 && mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0) { @@ -318,6 +401,9 @@ int main(int argc, char **argv) // ignore_convention // process m_aPackets while(m_NetChecker.Recv(&Packet)) { + // check if the server is banned + if(CheckBan(Packet.m_Address)) continue; + if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) { @@ -338,6 +424,13 @@ int main(int argc, char **argv) // ignore_convention } } + if(time_get()-LastBanReload > time_freq()*300) + { + LastBanReload = time_get(); + + ReloadBans(); + } + if(time_get()-LastBuild > time_freq()*5) { LastBuild = time_get();