Merge branch 'master' of git://github.com/GreYFoXGTi/DDRace

This commit is contained in:
heinrich5991 2011-01-26 20:11:49 +01:00
commit 0288655395
91 changed files with 3674 additions and 1182 deletions

5
.gitignore vendored
View file

@ -1,9 +1,12 @@
bam
.bam .bam
config.lua config.lua
datasrc/__pycache__ datasrc/__pycache__
datasrc/*.pyc datasrc/*.pyc
objs objs
src/game/generated src/game/generated
SDL.dll
autoexec.cfg
crapnet* crapnet*
dilate* dilate*
@ -23,7 +26,7 @@ buildlog.txt
autoexec.cfg autoexec.cfg
bam.exe bam.exe
*.bat *.bat
DDRace* DDRace*
DDRace-Server* DDRace-Server*
.cproject .cproject
.project .project

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 170 KiB

View file

@ -867,6 +867,9 @@ Select layer. Right click for properties.
Shift Shift
== ==
Sound error
==
Square Square
== ==
@ -882,6 +885,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -894,6 +900,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -858,6 +858,9 @@ Shift
Show chat Show chat
== ==
Sound error
==
Square Square
== ==
@ -876,6 +879,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -891,6 +897,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -963,6 +963,15 @@ no limit
Name plates size Name plates size
== ==
Sound error
==
The audio device couldn't be initialised.
==
Unable to delete the demo
==
##### old translations ##### ##### old translations #####
##### DDRace ##### ##### DDRace #####

View file

@ -864,6 +864,9 @@ Select layer. Right click for properties.
Shift Shift
== ==
Sound error
==
Square Square
== ==
@ -879,6 +882,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -894,6 +900,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -286,9 +286,6 @@ Grenade
Group Group
== Groupe == Groupe
HD
== HD
Hammer Hammer
== Maillet == Maillet
@ -900,6 +897,9 @@ Rotation of the envelope
Shift Shift
== ==
Sound error
==
Squares the current quad Squares the current quad
== ==
@ -912,6 +912,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -924,6 +927,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Use Clipping Use Clipping
== ==

View file

@ -10,6 +10,18 @@
%ds left %ds left
== Noch %ds == 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 Right click for context menu.
== %s Rechtsklick für Kontextmenü. == %s Rechtsklick für Kontextmenü.
@ -80,7 +92,7 @@ Automatically record demos
== Automatisch Demos aufnehmen == Automatisch Demos aufnehmen
Automatically take game over screenshot Automatically take game over screenshot
== Automatisch am Ende einer Runde ein Bildschirmfoto erstellen == Bildschirmfotos autom. nach jeder Runde erstellen
Blue team Blue team
== Blaues Team == Blaues Team
@ -484,6 +496,9 @@ Mute when not active
Name Name
== Name == Name
Name plates size
== Größe der Namen
Name: Name:
== Name: == Name:
@ -602,7 +617,7 @@ Quads
== Vier. == Vier.
Quality Textures Quality Textures
== Hochaufgelöste Texturen == Hochauflösende Texturen
Quick search: Quick search:
== Schnellsuche: == Schnellsuche:
@ -763,6 +778,9 @@ Skins
Sound Sound
== Ton == Ton
Sound error
== Audiofehler
Sound volume Sound volume
== Lautstärke == Lautstärke
@ -811,6 +829,9 @@ Teeworlds %s is out! Download it at www.teeworlds.com!
Texture Compression Texture Compression
== Texturkompression == 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. The server is running a non-standard tuning on a pure game type.
== Der Server läuft nicht mit Standardeinstellungen. == Der Server läuft nicht mit Standardeinstellungen.
@ -841,6 +862,9 @@ Type
UI Color UI Color
== Menüfarbe == Menüfarbe
Unable to delete the demo
== Demo konnte nicht gelöscht werden
Up Up
== Oben == Oben
@ -948,21 +972,6 @@ no limit
##### needs translation ##### ##### needs translation #####
%i minute left
==
%i minutes left
==
%i second left
==
%i seconds left
==
Name plates size
==
##### old translations ##### ##### old translations #####
##### DDRace ##### ##### DDRace #####

View file

@ -28,12 +28,18 @@ polish
portuguese portuguese
== Português == Português
romanian
== Română
russian russian
== Русский == Русский
serbian serbian
== Srpski == Srpski
spanish
== Español
swedish swedish
== Svenska == Svenska

File diff suppressed because it is too large Load diff

View file

@ -930,15 +930,24 @@ Rotation of the envelope
Shift Shift
== ==
Sound error
==
Stop record Stop record
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
Time limit: %d min Time limit: %d min
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -864,6 +864,9 @@ Select layer. Right click for properties.
Shift Shift
== ==
Sound error
==
Square Square
== ==
@ -879,6 +882,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -894,6 +900,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

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

@ -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 #####

View file

@ -930,15 +930,24 @@ Rotation of the envelope
Shift Shift
== ==
Sound error
==
Stop record Stop record
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
Time limit: %d min Time limit: %d min
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -864,6 +864,9 @@ Select layer. Right click for properties.
Shift Shift
== ==
Sound error
==
Square Square
== ==
@ -879,6 +882,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -894,6 +900,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

976
data/languages/spanish.txt Normal file
View file

@ -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 #####

View file

@ -855,6 +855,9 @@ Shift
Show chat Show chat
== ==
Sound error
==
Square Square
== ==
@ -873,6 +876,9 @@ Switch between images and layers managment.
Switch curve type Switch curve type
== ==
The audio device couldn't be initialised.
==
Tiles Tiles
== ==
@ -888,6 +894,9 @@ Toggle layer visibility
Toggles the envelope editor. Toggles the envelope editor.
== ==
Unable to delete the demo
==
Up Up
== ==

View file

@ -945,6 +945,15 @@ Rotation of the envelope
Shift Shift
== ==
Sound error
==
The audio device couldn't be initialised.
==
Unable to delete the demo
==
Up Up
== ==

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 282 KiB

View file

@ -31,6 +31,6 @@ for filename in sys.argv[1:]:
hash = hashlib.md5(f.encode()).hexdigest().lower()[16:] hash = hashlib.md5(f.encode()).hexdigest().lower()[16:]
# TODO: refactor hash that is equal to the 0.5 hash, remove when we # TODO: refactor hash that is equal to the 0.5 hash, remove when we
# TODO: remove when we don't need it any more # TODO: remove when we don't need it any more
if hash == "026b8eceb4cdd369": if hash == "f16c2456fc487748":
hash = "b67d1f1a1eea234e" hash = "b67d1f1a1eea234e"
print('#define GAME_NETVERSION_HASH "%s"' % hash) print('#define GAME_NETVERSION_HASH "%s"' % hash)

View file

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

View file

@ -77,6 +77,7 @@ public:
virtual void Quit() = 0; virtual void Quit() = 0;
virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0; virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0;
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp) = 0; virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;
virtual void DemoRecorder_Stop() = 0; virtual void DemoRecorder_Stop() = 0;
virtual void AutoScreenshot_Start() = 0; virtual void AutoScreenshot_Start() = 0;
@ -129,6 +130,8 @@ public:
virtual const char *ErrorString() = 0; virtual const char *ErrorString() = 0;
virtual const char *LatestVersion() = 0; virtual const char *LatestVersion() = 0;
virtual bool ConnectionProblems() = 0; virtual bool ConnectionProblems() = 0;
virtual bool SoundInitFailed() = 0;
}; };
class IGameClient : public IInterface class IGameClient : public IInterface
@ -148,6 +151,7 @@ public:
virtual void OnConnected() = 0; virtual void OnConnected() = 0;
virtual void OnMessage(int MsgId, CUnpacker *pUnpacker) = 0; virtual void OnMessage(int MsgId, CUnpacker *pUnpacker) = 0;
virtual void OnPredict() = 0; virtual void OnPredict() = 0;
virtual void OnActivateEditor() = 0;
virtual int OnSnapInput(int *pData) = 0; virtual int OnSnapInput(int *pData) = 0;

View file

@ -414,6 +414,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
m_WindowMustRefocus = 0; m_WindowMustRefocus = 0;
m_SnapCrcErrors = 0; m_SnapCrcErrors = 0;
m_AutoScreenshotRecycle = false; m_AutoScreenshotRecycle = false;
m_EditorActive = false;
m_AckGameTick = -1; m_AckGameTick = -1;
m_CurrentRecvTick = 0; m_CurrentRecvTick = 0;
@ -1466,11 +1467,11 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
} }
// adjust game time // adjust game time
if(m_RecivedSnapshots > 2)
{ {
int64 Now = m_GameTime.Get(time_get()); int64 Now = m_GameTime.Get(time_get());
int64 TickStart = GameTick*time_freq()/50; int64 TickStart = GameTick*time_freq()/50;
int64 TimeLeft = (TickStart-Now)*1000 / time_freq(); 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); m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0);
} }
@ -1807,7 +1808,7 @@ void CClient::Run()
m_pEditor->Init(); m_pEditor->Init();
// init sound, allowed to fail // init sound, allowed to fail
Sound()->Init(); m_SoundInitFailed = Sound()->Init() != 0;
// load data // load data
if(!LoadData()) if(!LoadData())
@ -1919,12 +1920,21 @@ void CClient::Run()
// render // render
if(g_Config.m_ClEditor) if(g_Config.m_ClEditor)
{ {
if(!m_EditorActive)
{
GameClient()->OnActivateEditor();
m_EditorActive = true;
}
Update(); Update();
m_pEditor->UpdateAndRender(); m_pEditor->UpdateAndRender();
m_pGraphics->Swap(); m_pGraphics->Swap();
} }
else else
{ {
if(m_EditorActive)
m_EditorActive = false;
Update(); Update();
if(g_Config.m_DbgStress) if(g_Config.m_DbgStress)
@ -2159,6 +2169,7 @@ void CClient::DemoRecorder_HandleAutoStart()
{ {
if(g_Config.m_ClAutoDemoRecord) if(g_Config.m_ClAutoDemoRecord)
{ {
DemoRecorder_Stop();
DemoRecorder_Start("auto/autorecord", true); DemoRecorder_Start("auto/autorecord", true);
if(g_Config.m_ClAutoDemoMax) if(g_Config.m_ClAutoDemoMax)
{ {

View file

@ -141,6 +141,8 @@ class CClient : public IClient, public CDemoPlayer::IListner
int m_WindowMustRefocus; int m_WindowMustRefocus;
int m_SnapCrcErrors; int m_SnapCrcErrors;
bool m_AutoScreenshotRecycle; bool m_AutoScreenshotRecycle;
bool m_EditorActive;
bool m_SoundInitFailed;
int m_AckGameTick; int m_AckGameTick;
int m_CurrentRecvTick; int m_CurrentRecvTick;
@ -234,6 +236,8 @@ public:
virtual bool ConnectionProblems(); virtual bool ConnectionProblems();
virtual bool SoundInitFailed() { return m_SoundInitFailed; }
void DirectInput(int *pInput, int Size); void DirectInput(int *pInput, int Size);
void SendInput(); void SendInput();

View file

@ -2,6 +2,7 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <algorithm> // sort #include <algorithm> // sort
#include <base/math.h>
#include <base/system.h> #include <base/system.h>
#include <engine/shared/network.h> #include <engine/shared/network.h>
#include <engine/shared/protocol.h> #include <engine/shared/protocol.h>
@ -449,9 +450,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
{ {
SetInfo(pEntry, *pInfo); SetInfo(pEntry, *pInfo);
if(m_ServerlistType == IServerBrowser::TYPE_LAN) 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<int>((time_get()-m_BroadcastTime)*1000/time_freq()), 999);
else else
pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999);
RemoveRequest(pEntry); RemoveRequest(pEntry);
} }
} }
@ -463,9 +464,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
SetInfo(pEntry, *pInfo); SetInfo(pEntry, *pInfo);
if(m_ServerlistType == IServerBrowser::TYPE_LAN) 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<int>((time_get()-m_BroadcastTime)*1000/time_freq()), 999);
else else
pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999);
RemoveRequest(pEntry); RemoveRequest(pEntry);
} }
} }
@ -748,4 +749,4 @@ void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr); str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr);
pConfig->WriteLine(aBuffer); pConfig->WriteLine(aBuffer);
} }
} }

View file

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

View file

@ -187,7 +187,7 @@ void CRegister::RegisterUpdate()
else else
{ {
char aBuf[256]; 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_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf);
m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = 0; m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = 0;
RegisterNewState(REGISTERSTATE_HEARTBEAT); RegisterNewState(REGISTERSTATE_HEARTBEAT);

View file

@ -190,6 +190,8 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
m_MapReload = 0; m_MapReload = 0;
memset(m_aPrevStates, CClient::STATE_EMPTY, MAX_CLIENTS * sizeof(int));
m_RconClientId = -1; m_RconClientId = -1;
Init(); 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_aClan[0] = 0;
pThis->m_aClients[ClientId].m_Authed = 0; pThis->m_aClients[ClientId].m_Authed = 0;
pThis->m_aClients[ClientId].m_AuthTries = 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)); memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR));
pThis->m_aClients[ClientId].m_Snapshots.PurgeAll(); pThis->m_aClients[ClientId].m_Snapshots.PurgeAll();
return 0; return 0;
@ -631,14 +634,14 @@ void CServer::SendRconLineAuthed(const char *pLine, void *pUser)
void CServer::SendRconResponse(const char *pLine, void *pUser) void CServer::SendRconResponse(const char *pLine, void *pUser)
{ {
RconResponseInfo *pInfo = (RconResponseInfo *)pUser; RconResponseInfo *pInfo = (RconResponseInfo *)pUser;
CServer *pThis = pInfo->m_Server; CServer *pThis = pInfo->m_Server;
static volatile int ReentryGuard = 0; static volatile int ReentryGuard = 0;
if(ReentryGuard) if(ReentryGuard)
return; return;
ReentryGuard++; ReentryGuard++;
if(pThis->m_aClients[pInfo->m_ClientId].m_State != CClient::STATE_EMPTY) if(pThis->m_aClients[pInfo->m_ClientId].m_State != CClient::STATE_EMPTY)
pThis->SendRconLine(pInfo->m_ClientId, pLine); pThis->SendRconLine(pInfo->m_ClientId, pLine);
@ -903,22 +906,24 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
} }
else else
{ {
char aHex[] = "0123456789ABCDEF"; if(g_Config.m_Debug)
char aBuf[512];
for(int b = 0; b < pPacket->m_DataSize && b < 32; b++)
{ {
aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; char aHex[] = "0123456789ABCDEF";
aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; char aBuf[512];
aBuf[b*3+2] = ' ';
aBuf[b*3+3] = 0;
}
char aBufMsg[256]; for(int b = 0; b < pPacket->m_DataSize && b < 32; b++)
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); aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4];
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); 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 else
@ -1145,6 +1150,11 @@ int CServer::LoadMap(const char *pMapName)
io_read(File, m_pCurrentMapData, m_CurrentMapSize); io_read(File, m_pCurrentMapData, m_CurrentMapSize);
io_close(File); io_close(File);
} }
for(int i=0; i<MAX_CLIENTS; i++) {
m_aPrevStates[i] = m_aClients[i].m_State;
}
return 1; return 1;
} }
@ -1378,7 +1388,7 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1)
CServer *pServer = (CServer *)pUser; CServer *pServer = (CServer *)pUser;
const char *pStr = pResult->GetString(0); const char *pStr = pResult->GetString(0);
int Minutes = 30; int Minutes = 30;
const char *pReason = "No reason given"; const char *pReason = "No reason given";
if(pResult->NumArguments() > 1) if(pResult->NumArguments() > 1)
Minutes = pResult->GetInteger(1); Minutes = pResult->GetInteger(1);
@ -1394,7 +1404,7 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1)
Addr.port = AddrCheck.port = 0; Addr.port = AddrCheck.port = 0;
if(net_addr_comp(&Addr, &AddrCheck) == 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; 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) 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; return;
} }
} }
@ -1761,7 +1771,7 @@ void CServer::SetRconLevel(int ClientId, int Level)
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
Msg.AddInt(0); Msg.AddInt(0);
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientId, true);
m_aClients[ClientId].m_Authed = Level; m_aClients[ClientId].m_Authed = 0;
} }
else else
{ {

View file

@ -109,6 +109,7 @@ public:
}; };
CClient m_aClients[MAX_CLIENTS]; CClient m_aClients[MAX_CLIENTS];
int m_aPrevStates[MAX_CLIENTS];
CSnapshotDelta m_SnapshotDelta; CSnapshotDelta m_SnapshotDelta;
CSnapshotBuilder m_SnapshotBuilder; CSnapshotBuilder m_SnapshotBuilder;
@ -180,8 +181,8 @@ public:
struct RconResponseInfo struct RconResponseInfo
{ {
CServer *m_Server; CServer *m_Server;
int m_ClientId; int m_ClientId;
}; };
void ProcessClientPacket(CNetChunk *pPacket); void ProcessClientPacket(CNetChunk *pPacket);

View file

@ -22,10 +22,11 @@ enum
CFGFLAG_CLIENT=2, CFGFLAG_CLIENT=2,
CFGFLAG_SERVER=4, CFGFLAG_SERVER=4,
CFGFLAG_STORE=8, CFGFLAG_STORE=8,
CFGFLAG_MASTER=16,
//DDRace //DDRace
CMDFLAG_CHEAT=16, CMDFLAG_CHEAT=32,
CMDFLAG_TIMER=32, CMDFLAG_TIMER=64,
CMDFLAG_HELPERCMD=64 CMDFLAG_HELPERCMD=128
}; };
#endif #endif

View file

@ -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(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(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(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) 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 #endif
MACRO_CONFIG_INT(SvCheats, sv_cheats, 0, 0, 1, CFGFLAG_SERVER, "Turns cheats on/off", 4) 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(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(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) MACRO_CONFIG_INT(SvEndlessSuperHook, sv_endless_super_hook, 0, 0, 1, CFGFLAG_SERVER, "Endless hook for super players on/off", 4)

View file

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

View file

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

View file

@ -4,7 +4,7 @@
void CLineReader::Init(IOHANDLE io) void CLineReader::Init(IOHANDLE io)
{ {
m_BufferMaxSize = 4*1024; m_BufferMaxSize = sizeof(m_aBuffer);
m_BufferSize = 0; m_BufferSize = 0;
m_BufferPos = 0; m_BufferPos = 0;
m_IO = io; m_IO = io;
@ -13,6 +13,7 @@ void CLineReader::Init(IOHANDLE io)
char *CLineReader::Get() char *CLineReader::Get()
{ {
unsigned LineStart = m_BufferPos; unsigned LineStart = m_BufferPos;
bool CRLFBreak = false;
while(1) while(1)
{ {
@ -53,10 +54,25 @@ char *CLineReader::Get()
if(m_aBuffer[m_BufferPos] == '\n' || m_aBuffer[m_BufferPos] == '\r') if(m_aBuffer[m_BufferPos] == '\n' || m_aBuffer[m_BufferPos] == '\r')
{ {
// line found // 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_aBuffer[m_BufferPos] = 0;
m_BufferPos++;
return &m_aBuffer[LineStart]; return &m_aBuffer[LineStart];
} }
else else

View file

@ -80,7 +80,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot)
for(int i = 0; i < pSnapshot->NumItems(); i++) for(int i = 0; i < pSnapshot->NumItems(); i++)
{ {
int Key = pSnapshot->GetItem(i)->Key(); 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) if(pHashlist[HashID].m_Num != 64)
{ {
pHashlist[HashID].m_aIndex[pHashlist[HashID].m_Num] = i; 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) 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++) for(int i = 0; i < pHashlist[HashID].m_Num; i++)
{ {
if(pHashlist[HashID].m_aKeys[i] == Key) 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) 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); CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize);
mem_zero(pObj, sizeof(CSnapshotItem) + Size); 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_aOffsets[m_NumItems] = m_DataSize;
m_DataSize += sizeof(CSnapshotItem) + Size; m_DataSize += sizeof(CSnapshotItem) + Size;
m_NumItems++; m_NumItems++;
dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data");
dbg_assert(m_NumItems < MAX_ITEMS, "too many items");
return pObj->Data(); return pObj->Data();
} }

View file

@ -114,7 +114,7 @@ class CSnapshotBuilder
{ {
enum enum
{ {
MAX_ITEMS = 1024*2 MAX_ITEMS = 1024
}; };
char m_aData[CSnapshot::MAX_SIZE]; char m_aData[CSnapshot::MAX_SIZE];

View file

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

View file

@ -1,6 +1,8 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/tl/string.h>
#include <engine/graphics.h> #include <engine/graphics.h>
#include <engine/textrender.h> #include <engine/textrender.h>
#include <engine/keys.h> #include <engine/keys.h>

View file

@ -5,6 +5,7 @@
#include <game/generated/client_data.h> #include <game/generated/client_data.h>
#include <base/system.h> #include <base/system.h>
#include <base/tl/sorted_array.h>
#include <engine/shared/ringbuffer.h> #include <engine/shared/ringbuffer.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>

View file

@ -2,6 +2,8 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/math.h> #include <base/math.h>
#include <base/tl/sorted_array.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <game/collision.h> #include <game/collision.h>
@ -32,6 +34,11 @@ void CControls::OnReset()
m_InputDirectionRight = 0; m_InputDirectionRight = 0;
} }
void CControls::OnRelease()
{
OnReset();
}
void CControls::OnPlayerDeath() void CControls::OnPlayerDeath()
{ {
m_LastData.m_WantedWeapon = m_InputData.m_WantedWeapon = 0; m_LastData.m_WantedWeapon = m_InputData.m_WantedWeapon = 0;

View file

@ -19,6 +19,7 @@ public:
CControls(); CControls();
virtual void OnReset(); virtual void OnReset();
virtual void OnRelease();
virtual void OnRender(); virtual void OnRender();
virtual void OnMessage(int MsgType, void *pRawMsg); virtual void OnMessage(int MsgType, void *pRawMsg);
virtual bool OnMouseMove(float x, float y); virtual bool OnMouseMove(float x, float y);

View file

@ -1,5 +1,7 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/tl/sorted_array.h>
#include <engine/demo.h> #include <engine/demo.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>

View file

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

View file

@ -759,6 +759,14 @@ int CMenus::Render()
// some margin around the screen // some margin around the screen
Screen.Margin(10.0f, &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) if(m_Popup == POPUP_NONE)
{ {
// do tab bar // do tab bar
@ -848,6 +856,13 @@ int CMenus::Render()
pExtraText = Localize("Are you sure that you want to delete the demo?"); pExtraText = Localize("Are you sure that you want to delete the demo?");
ExtraAlign = -1; 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) else if(m_Popup == POPUP_PASSWORD)
{ {
pTitle = Localize("Password incorrect"); pTitle = Localize("Password incorrect");
@ -1111,6 +1126,10 @@ void CMenus::SetActive(bool Active)
m_pClient->OnRelease(); m_pClient->OnRelease();
} }
} }
else if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
m_pClient->OnRelease();
}
} }
void CMenus::OnReset() void CMenus::OnReset()

View file

@ -97,6 +97,7 @@ class CMenus : public CComponent
POPUP_PURE, POPUP_PURE,
POPUP_LANGUAGE, POPUP_LANGUAGE,
POPUP_DELETE_DEMO, POPUP_DELETE_DEMO,
POPUP_SOUNDERROR,
POPUP_PASSWORD, POPUP_PASSWORD,
POPUP_QUIT, POPUP_QUIT,
}; };

View file

@ -148,9 +148,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
if(ScrollNum > 0) if(ScrollNum > 0)
{ {
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
s_ScrollValue -= 1.0f/ScrollNum; s_ScrollValue -= 3.0f/ScrollNum;
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
s_ScrollValue += 1.0f/ScrollNum; s_ScrollValue += 3.0f/ScrollNum;
} }
else else
ScrollNum = 0; ScrollNum = 0;
@ -464,7 +464,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing); str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing);
static float Offset = 0.0f; static float Offset = 0.0f;
DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), 12.0f, &Offset); 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); View.HSplitBottom(ms_ButtonHeight, &View, &Button);
@ -498,6 +498,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0); ServerDetails.HSplitBottom(10.0f, &ServerDetails, 0x0);
// server details // server details
CTextCursor Cursor;
const float FontSize = 12.0f; const float FontSize = 12.0f;
ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails); ServerDetails.HSplitTop(20.0f, &ServerHeader, &ServerDetails);
RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
@ -545,15 +546,21 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
} }
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, pSelectedServer->m_aVersion, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aVersion, -1);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, pSelectedServer->m_aGameType, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aGameType, -1);
char aTemp[16]; char aTemp[16];
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency); str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn); RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
UI()->DoLabelScaled(&Row, aTemp, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
} }
@ -579,11 +586,12 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard); ServerScoreBoard.HSplitTop(16.0f, &Row, &ServerScoreBoard);
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score); str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aPlayers[i].m_Score);
UI()->DoLabelScaled(&Row, aTemp, FontSize, -1); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = 25.0f;
TextRender()->TextEx(&Cursor, aTemp, -1);
Row.VSplitLeft(25.0f, 0x0, &Row); Row.VSplitLeft(25.0f, 0x0, &Row);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); TextRender()->SetCursor(&Cursor, Row.x, Row.y, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w; Cursor.m_LineWidth = Row.w;

View file

@ -3,6 +3,8 @@
#include <base/math.h> #include <base/math.h>
#include <base/tl/string.h>
#include <engine/demo.h> #include <engine/demo.h>
#include <engine/keys.h> #include <engine/keys.h>
#include <engine/graphics.h> #include <engine/graphics.h>
@ -130,8 +132,9 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
if(CurrentTick == TotalTicks) if(CurrentTick == TotalTicks)
{ {
DemoPlayer()->Pause(); m_pClient->OnReset();
DemoPlayer()->SetPos(0); DemoPlayer()->Pause();
DemoPlayer()->SetPos(0);
} }
if(m_MenuActive) if(m_MenuActive)
@ -160,6 +163,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
static int s_ResetButton = 0; static int s_ResetButton = 0;
if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button)) if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button))
{ {
m_pClient->OnReset();
DemoPlayer()->Pause(); DemoPlayer()->Pause();
DemoPlayer()->SetPos(0); DemoPlayer()->SetPos(0);
} }
@ -279,9 +283,9 @@ void CMenus::UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight,
if(Num > 0) if(Num > 0)
{ {
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
gs_ListBoxScrollValue -= 1.0f/Num; gs_ListBoxScrollValue -= 3.0f/Num;
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) 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 < 0.0f) gs_ListBoxScrollValue = 0.0f;
if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;

View file

@ -2,6 +2,8 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/math.h> #include <base/math.h>
#include <base/tl/string.h>
#include <engine/demo.h> #include <engine/demo.h>
#include <engine/serverbrowser.h> #include <engine/serverbrowser.h>
#include <engine/textrender.h> #include <engine/textrender.h>

View file

@ -3,6 +3,7 @@
#include <base/math.h> #include <base/math.h>
#include <base/tl/string.h>
#include <engine/graphics.h> #include <engine/graphics.h>
#include <engine/storage.h> #include <engine/storage.h>

View file

@ -1,5 +1,7 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/tl/sorted_array.h>
#include <engine/demo.h> #include <engine/demo.h>
#include <engine/graphics.h> #include <engine/graphics.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
@ -121,9 +123,6 @@ void CPlayers::RenderHook(
float IntraTick = Client()->IntraGameTick(); float IntraTick = Client()->IntraGameTick();
if(Player.m_Health < 0) // dont render dead players
return;
// set size // set size
RenderInfo.m_Size = 64.0f; RenderInfo.m_Size = 64.0f;
@ -131,7 +130,7 @@ void CPlayers::RenderHook(
// use preditect players if needed // use preditect players if needed
if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) 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 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); 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 // draw hook
if (Prev.m_HookState>0 && Player.m_HookState>0) if (Prev.m_HookState>0 && Player.m_HookState>0)
{ {
@ -254,9 +250,6 @@ void CPlayers::RenderPlayer(
float IntraTick = Client()->IntraGameTick(); 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 = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f;
//float angle = 0; //float angle = 0;
@ -292,7 +285,7 @@ void CPlayers::RenderPlayer(
// use preditect players if needed // use preditect players if needed
if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) 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 else
@ -322,9 +315,6 @@ void CPlayers::RenderPlayer(
m_pClient->m_pEffects->AirJump(Position); 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 Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1;
bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16); 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); bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);

View file

@ -1,5 +1,7 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/tl/string.h>
#include <engine/demo.h> #include <engine/demo.h>
#include <engine/graphics.h> #include <engine/graphics.h>
#include <engine/textrender.h> #include <engine/textrender.h>
@ -53,32 +55,26 @@ void CScoreboard::RenderGoals(float x, float y, float w)
Graphics()->QuadsEnd(); Graphics()->QuadsEnd();
// render goals // render goals
//y = ystart+h-54;
float tw = 0.0f;
if(m_pClient->m_Snap.m_pGameobj) if(m_pClient->m_Snap.m_pGameobj)
{ {
if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit) if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit)
{ {
char aBuf[64]; char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit); 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); TextRender()->Text(0, x, y, 20.0f, aBuf, -1);
tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1);
} }
if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit) if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit)
{ {
char aBuf[64]; char aBuf[64];
str_format(aBuf, sizeof(aBuf), Localize("Time limit: %d min"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit); 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); TextRender()->Text(0, x+220.0f, y, 20.0f, aBuf, -1);
tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1);
} }
if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent) if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent)
{ {
char aBuf[64]; 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); 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); float tw = TextRender()->TextWidth(0, 20.0f, aBuf, -1);
TextRender()->Text(0, x+w-tw-20.0f, y, 20.0f, aBuf, -1);
/*[48c3fd4c][game/scoreboard]: timelimit x:219.428558
[48c3fd4c][game/scoreboard]: round x:453.142822*/
} }
} }
} }
@ -110,7 +106,7 @@ void CScoreboard::RenderSpectators(float x, float y, float w)
{ {
if(Count) if(Count)
str_append(aBuffer, ", ", sizeof(aBuffer)); 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) if (g_Config.m_ClShowIds)
{ {
char aId[4]; 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) void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const char *pTitle)
{ {
if(Team == TEAM_SPECTATORS)
return;
//float ystart = y; //float ystart = y;
float h = 750.0f; float h = 740.0f;
Graphics()->BlendNormal(); Graphics()->BlendNormal();
Graphics()->TextureSet(-1); Graphics()->TextureSet(-1);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
Graphics()->SetColor(0,0,0,0.5f); 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(); Graphics()->QuadsEnd();
// render title // render title
@ -150,64 +149,23 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
float Offset = 80.0f; float Offset = 80.0f;
float DataOffset = 130; float DataOffset = 130;
float tw = TextRender()->TextWidth(0, 48, pTitle, -1); float tw = TextRender()->TextWidth(0, 48, pTitle, -1);
TextRender()->Text(0, x+10, y, 48, pTitle, -1);
if(Team == TEAM_SPECTATORS) if(m_GameType.find("Race") == std::string::npos)
{ if(m_pClient->m_Snap.m_pGameobj)
TextRender()->Text(0, x+w/2-tw/2, y, 48, pTitle, -1); {
} char aBuf[128];
else int Score = Team == TEAM_RED ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed : m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue;
{ str_format(aBuf, sizeof(aBuf), "%d", Score);
TextRender()->Text(0, x+10, y, 48, pTitle, -1); tw = TextRender()->TextWidth(0, 48, aBuf, -1);
if(str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1);
if(m_pClient->m_Snap.m_pGameobj) }
{
char aBuf[128];
int Score = Team == TEAM_RED ? m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed : m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue;
str_format(aBuf, sizeof(aBuf), "%d", Score);
tw = TextRender()->TextWidth(0, 48, aBuf, -1);
TextRender()->Text(0, x+w-tw-30, y, 48, aBuf, -1);
}
}
y += 54.0f; y += 54.0f;
// find players
const CNetObj_PlayerInfo *paPlayers[MAX_CLIENTS] = {0};
int NumPlayers = 0;
for(int i = 0; i < Client()->SnapNumItems(IClient::SNAP_CURRENT); i++)
{
IClient::CSnapItem Item;
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
{
const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
if(pInfo->m_Team == Team)
{
paPlayers[NumPlayers] = pInfo;
if(++NumPlayers == MAX_CLIENTS)
break;
}
}
}
// sort players
for(int k = 0; k < NumPlayers-1; k++) // ffs, bubblesort
{
for(int i = 0; i < NumPlayers-k-1; i++)
{
if((str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace") && (paPlayers[i]->m_Score < paPlayers[i+1]->m_Score)) || (!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace") && (m_pClient->m_aClients[paPlayers[i]->m_ClientId].m_Score == 0 || (m_pClient->m_aClients[paPlayers[i]->m_ClientId].m_Score > m_pClient->m_aClients[paPlayers[i+1]->m_ClientId].m_Score && m_pClient->m_aClients[paPlayers[i+1]->m_ClientId].m_Score != 0))))
{
const CNetObj_PlayerInfo *pTmp = paPlayers[i];
paPlayers[i] = paPlayers[i+1];
paPlayers[i+1] = pTmp;
}
}
}
// render headlines // render headlines
TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1); TextRender()->Text(0, x+10, y, 24.0f, Localize("Score"), -1);
if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) if(m_GameType.find("Race") != std::string::npos)
{ {
TextRender()->Text(0, x+125+Offset, y, 24.0f, Localize("Name"), -1); TextRender()->Text(0, x+125+Offset, y, 24.0f, Localize("Name"), -1);
TextRender()->Text(0, x+w-75, y, 24.0f, Localize("Ping"), -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 TeeSizeMod = 1.0f;
float TeeOffset = 0.0f; float TeeOffset = 0.0f;
if(NumPlayers > 13) if(m_pClient->m_Snap.m_aTeamSize[Team] > 13)
{ {
FontSize = 30.0f; FontSize = 30.0f;
LineHeight = 40.0f; LineHeight = 40.0f;
@ -233,9 +191,11 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
} }
// render player scores // render player scores
for(int i = 0; i < NumPlayers; i++) for(int i = 0; i < MAX_CLIENTS; i++)
{ {
const CNetObj_PlayerInfo *pInfo = paPlayers[i]; const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByScore[i];
if(!pInfo || pInfo->m_Team != Team)
continue;
// make sure that we render the correct team // make sure that we render the correct team
@ -252,7 +212,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
float FontSizeResize = FontSize; float FontSizeResize = FontSize;
float Width; 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 ScoreWidth = 150.0f;
const float PingWidth = 60.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; float size = 64.0f;
IGraphics::CQuadItem QuadItem; 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); QuadItem = IGraphics::CQuadItem(x+55+DataOffset, y-15, size/2, size);
else else
QuadItem = IGraphics::CQuadItem(x+55, y-15, size/2, size); 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; CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientId].m_RenderInfo;
TeeInfo.m_Size *= TeeSizeMod; 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)); RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+50+DataOffset, y+28+TeeOffset));
else else
RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+TeeOffset)); 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() void CScoreboard::OnRender()
{ {
bool DoScoreBoard = false; if(!Active())
// 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)
return; return;
m_GameType = std::string(m_pServerInfo.m_aGameType);
// if the score board is active, then we should clear the motd message aswell // if the score board is active, then we should clear the motd message aswell
if(m_pClient->m_pMotd->IsActive()) if(m_pClient->m_pMotd->IsActive())
m_pClient->m_pMotd->Clear(); m_pClient->m_pMotd->Clear();
@ -401,16 +344,13 @@ void CScoreboard::OnRender()
Graphics()->MapScreen(0, 0, Width, Height); Graphics()->MapScreen(0, 0, Width, Height);
float w; float w;
if(!str_comp_nocase(m_pServerInfo.m_aGameType, "DDRace")) if(m_GameType.find("Race") != std::string::npos)
w = 750.0f; w = 750.0f;
else else
w = 650.0f; w = 650.0f;
if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)) 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); RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
//render_scoreboard(gameobj, 0, 0, -1, 0);
}
else 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) else if(m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue > m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed)
pText = Localize("Blue team wins!"); pText = Localize("Blue team wins!");
float w = TextRender()->TextWidth(0, 92.0f, pText, -1); float w = TextRender()->TextWidth(0, 86.0f, pText, -1);
TextRender()->Text(0, Width/2-w/2, 45, 92.0f, pText, -1); TextRender()->Text(0, Width/2-w/2, 39, 86.0f, pText, -1);
} }
RenderScoreboard(Width/2-w-20, 150.0f, w, TEAM_RED, Localize("Red team")); RenderScoreboard(Width/2-w-20, 150.0f, w, TEAM_RED, Localize("Red team"));
@ -437,5 +377,20 @@ void CScoreboard::OnRender()
bool CScoreboard::Active() 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;
} }

View file

@ -4,6 +4,7 @@
#define GAME_CLIENT_COMPONENTS_SCOREBOARD_H #define GAME_CLIENT_COMPONENTS_SCOREBOARD_H
#include <game/client/component.h> #include <game/client/component.h>
#include <engine/serverbrowser.h> #include <engine/serverbrowser.h>
#include <string>
class CScoreboard : public CComponent class CScoreboard : public CComponent
{ {
@ -16,6 +17,7 @@ class CScoreboard : public CComponent
bool m_Active; bool m_Active;
CServerInfo m_pServerInfo; CServerInfo m_pServerInfo;
std::string m_GameType;
public: public:
CScoreboard(); CScoreboard();

View file

@ -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", "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("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("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); 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(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 // don't use predicted
} }
@ -631,6 +632,12 @@ void CGameClient::OnGameOver()
Client()->AutoScreenshot_Start(); Client()->AutoScreenshot_Start();
} }
void CGameClient::OnStartGame()
{
if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
Client()->DemoRecorder_HandleAutoStart();
}
void CGameClient::OnRconLine(const char *pLine) void CGameClient::OnRconLine(const char *pLine)
{ {
m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine);
@ -821,6 +828,8 @@ void CGameClient::OnNewSnapshot()
m_Snap.m_pGameobj = (CNetObj_Game *)pData; m_Snap.m_pGameobj = (CNetObj_Game *)pData;
if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0) if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0)
OnGameOver(); OnGameOver();
else if(s_GameOver != 0 && m_Snap.m_pGameobj->m_GameOver == 0)
OnStartGame();
s_GameOver = m_Snap.m_pGameobj->m_GameOver; s_GameOver = m_Snap.m_pGameobj->m_GameOver;
} }
else if(Item.m_Type == NETOBJTYPE_FLAG) else if(Item.m_Type == NETOBJTYPE_FLAG)
@ -846,6 +855,21 @@ void CGameClient::OnNewSnapshot()
} }
else else
m_Snap.m_Spectate = true; m_Snap.m_Spectate = true;
// sort player infos by score
mem_copy(m_Snap.m_paInfoByScore, m_Snap.m_paPlayerInfos, sizeof(m_Snap.m_paInfoByScore));
for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort
{
for(int i = 0; i < MAX_CLIENTS-k-1; i++)
{
if(m_Snap.m_paInfoByScore[i+1] && (!m_Snap.m_paInfoByScore[i] || m_Snap.m_paInfoByScore[i]->m_Score < m_Snap.m_paInfoByScore[i+1]->m_Score))
{
const CNetObj_PlayerInfo *pTmp = m_Snap.m_paInfoByScore[i];
m_Snap.m_paInfoByScore[i] = m_Snap.m_paInfoByScore[i+1];
m_Snap.m_paInfoByScore[i+1] = pTmp;
}
}
}
CTuningParams StandardTuning; CTuningParams StandardTuning;
CServerInfo CurrentServerInfo; CServerInfo CurrentServerInfo;
@ -996,6 +1020,11 @@ void CGameClient::OnPredict()
m_PredictedTick = Client()->PredGameTick(); m_PredictedTick = Client()->PredGameTick();
} }
void CGameClient::OnActivateEditor()
{
OnRelease();
}
void CGameClient::CClientData::UpdateRenderInfo() void CGameClient::CClientData::UpdateRenderInfo()
{ {
m_RenderInfo = m_SkinInfo; m_RenderInfo = m_SkinInfo;

View file

@ -182,11 +182,13 @@ public:
virtual void OnMessage(int MsgId, CUnpacker *pUnpacker); virtual void OnMessage(int MsgId, CUnpacker *pUnpacker);
virtual void OnNewSnapshot(); virtual void OnNewSnapshot();
virtual void OnPredict(); virtual void OnPredict();
virtual void OnActivateEditor();
virtual int OnSnapInput(int *pData); virtual int OnSnapInput(int *pData);
virtual void OnShutdown(); virtual void OnShutdown();
virtual void OnEnterGame(); virtual void OnEnterGame();
virtual void OnRconLine(const char *pLine); virtual void OnRconLine(const char *pLine);
virtual void OnGameOver(); virtual void OnGameOver();
virtual void OnStartGame();
virtual const char *GetItemName(int Type); virtual const char *GetItemName(int Type);
virtual const char *Version(); virtual const char *Version();

View file

@ -89,7 +89,7 @@ void CCollision::Init(class CLayers *pLayers)
Index = m_pSwitch[i].m_Type; Index = m_pSwitch[i].m_Type;
if(Index <= TILE_NPH) if(Index <= TILE_NPH)
{ {
if(Index >= TILE_SWITCHTIMEDOPEN && Index <= TILE_SWITCHCLOSE) if(Index >= TILE_FREEZE && Index <= TILE_SWITCHCLOSE)
m_pSwitch[i].m_Type = Index; m_pSwitch[i].m_Type = Index;
else else
m_pSwitch[i].m_Type = 0; m_pSwitch[i].m_Type = 0;
@ -119,7 +119,7 @@ void CCollision::Init(class CLayers *pLayers)
} }
// DDRace tiles // 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; m_pFront[i].m_Index = Index;
} }
} }
@ -145,7 +145,7 @@ void CCollision::Init(class CLayers *pLayers)
} }
// DDRace tiles // 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; 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 nx = clamp(x/32, 0, m_Width-1);
int ny = clamp(y/32, 0, m_Height-1); int ny = clamp(y/32, 0, m_Height-1);
if(!m_pTiles || ny < 0 || nx < 0) 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); //dbg_msg("Collision","Something is terribly wrong, !m_pTiles %d, ny %d, ny %d", !m_pTiles, ny, ny);
return 0; return 0;
} }
/*dbg_msg("GetTile","m_Index %d",m_pTiles[ny*m_Width+nx].m_Index);//Remove */ /*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 if(m_pTiles[ny*m_Width+nx].m_Index == COLFLAG_SOLID
|| m_pTiles[ny*m_Width+nx].m_Index == (COLFLAG_SOLID|COLFLAG_NOHOOK) || m_pTiles[ny*m_Width+nx].m_Index == (COLFLAG_SOLID|COLFLAG_NOHOOK)
@ -404,14 +404,14 @@ int CCollision::IsSpeedup(int Index)
return false; return false;
if(m_pSpeedup[Index].m_Force > 0) if(m_pSpeedup[Index].m_Force > 0)
return m_pSpeedup[Index].m_Type; return Index;
return 0; return 0;
} }
void CCollision::GetSpeedup(int Index, vec2 *Dir, int *Force, int *MaxSpeed) void CCollision::GetSpeedup(int Index, vec2 *Dir, int *Force, int *MaxSpeed)
{ {
if(Index < 0) if(Index < 0 || !m_pSpeedup)
return; return;
vec2 Direction = vec2(1, 0); vec2 Direction = vec2(1, 0);
float Angle = m_pSpeedup[Index].m_Angle * (pi / 180.0f); float Angle = m_pSpeedup[Index].m_Angle * (pi / 180.0f);
@ -429,7 +429,7 @@ int CCollision::IsSwitch(int Index)
if(!m_pSwitch) if(!m_pSwitch)
return false; 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 m_pSwitch[Index].m_Type;
return 0; return 0;
@ -457,13 +457,13 @@ int CCollision::GetSwitchDelay(int Index)
if(!m_pSwitch) if(!m_pSwitch)
return false; 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 m_pSwitch[Index].m_Delay;
return 0; 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 nx = clamp(x/32, 0, m_Width-1);
int ny = clamp(y/32, 0, m_Height-1); int ny = clamp(y/32, 0, m_Height-1);
@ -694,7 +694,7 @@ int CCollision::Entity(int x, int y, int Layer)
default: default:
str_format(aBuf,sizeof(aBuf), "Unknown"); 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; return 0;
} }
switch (Layer) switch (Layer)

View file

@ -91,7 +91,7 @@ public:
int IsCheckpoint(int Index); int IsCheckpoint(int Index);
int IsFCheckpoint(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); vec2 CpSpeed(int index, int Flags = 0);

View file

@ -6,13 +6,13 @@
#define CONSOLE_COMMAND(name, params, flags, callback, userdata, help, level) #define CONSOLE_COMMAND(name, params, flags, callback, userdata, help, level)
#endif #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("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("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("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("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("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("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("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("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) CONSOLE_COMMAND("timerstop", "v", CFGFLAG_SERVER|CMDFLAG_TIMER, ConTimerStop, this, "Stops the timer of player v", 2)

View file

@ -3,6 +3,8 @@
#include <base/system.h> #include <base/system.h>
#include <base/tl/array.h>
#include <engine/shared/datafile.h> #include <engine/shared/datafile.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <engine/shared/engine.h> #include <engine/shared/engine.h>

View file

@ -1,5 +1,7 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/tl/array.h>
#include <engine/client.h> #include <engine/client.h>
#include <engine/console.h> #include <engine/console.h>
#include <engine/graphics.h> #include <engine/graphics.h>

View file

@ -1101,7 +1101,7 @@ void CLayerSwitch::BrushDraw(CLayer *pBrush, float wx, float wy)
if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height) if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height)
continue; 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) 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_pSwitchTile[fy*m_Width+fx].m_Delay = 0;
m_pTiles[fy*m_Width+fx].m_Index = 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;
}
} }
} }

View file

@ -362,18 +362,19 @@ void CCharacterCore::Tick(bool UseInput)
// handle player <-> player collision // handle player <-> player collision
float d = distance(m_Pos, p->m_Pos); float d = distance(m_Pos, p->m_Pos);
vec2 Dir = normalize(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) if(d < PhysSize*1.25f && d > 1.0f)
{ {
float a = (PhysSize*1.45f - d); float a = (PhysSize*1.45f - d);
float v = 0.5f;
// make sure that we don't add excess force by checking the // make sure that we don't add excess force by checking the
// direction against the current velocity // direction against the current velocity. if not zero.
vec2 VelDir = normalize(m_Vel); if (length(m_Vel) > 0.0001)
float v = 1-(dot(VelDir, Dir)+1)/2; v = 1-(dot(normalize(m_Vel), Dir)+1)/2;
m_Vel = m_Vel + Dir*a*(v*0.75f);
m_Vel = m_Vel * 0.85f; m_Vel += Dir*a*(v*0.75f);
m_Vel *= 0.85f;
} }
} }
// handle hook influence // handle hook influence

View file

@ -91,6 +91,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon
pReplacement += 3; pReplacement += 3;
AddString(pLine, pReplacement); AddString(pLine, pReplacement);
} }
io_close(IoHandle);
m_CurrentVersion = ++m_VersionCounter; m_CurrentVersion = ++m_VersionCounter;
return true; return true;

View file

@ -90,6 +90,10 @@ enum
TILE_FREEZE = 9, TILE_FREEZE = 9,
TILE_TELEINEVIL, TILE_TELEINEVIL,
TILE_UNFREEZE, TILE_UNFREEZE,
TILE_DFREEZE,
TILE_DUNFREEZE,
TILE_EHOOK_START = 17,
TILE_EHOOK_END,
//Switches //Switches
TILE_SWITCHTIMEDOPEN = 22, TILE_SWITCHTIMEDOPEN = 22,
TILE_SWITCHTIMEDCLOSE, TILE_SWITCHTIMEDCLOSE,

View file

@ -5,20 +5,6 @@
#include <game/server/gamemodes/DDRace.h> #include <game/server/gamemodes/DDRace.h>
#include <game/version.h> #include <game/version.h>
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) void CGameContext::ConGoLeft(IConsole::IResult *pResult, void *pUserData, int ClientId)
{ {
CGameContext *pSelf = (CGameContext *)pUserData; CGameContext *pSelf = (CGameContext *)pUserData;
@ -78,14 +64,46 @@ void CGameContext::ConMute(IConsole::IResult *pResult, void *pUserData, int Clie
if(Seconds < 10) if(Seconds < 10)
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(); 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); 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); 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) void CGameContext::ConSetlvl3(IConsole::IResult *pResult, void *pUserData, int ClientId)
{ {
CGameContext *pSelf = (CGameContext *)pUserData; 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) void CGameContext::ConFreeze(IConsole::IResult *pResult, void *pUserData, int ClientId)
{ {
CGameContext *pSelf = (CGameContext *)pUserData; CGameContext *pSelf = (CGameContext *)pUserData;
int time=-1; int Seconds = -1;
int Victim = pResult->GetVictim(); int Victim = pResult->GetVictim();
char buf[128]; char buf[128];
if(pResult->NumArguments() >= 1) if(pResult->NumArguments())
time = clamp(pResult->GetInteger(1), -1, 29999); Seconds = clamp(pResult->GetInteger(0), -2, 9999);
CCharacter* chr = pSelf->GetPlayerChar(Victim); CCharacter* pChr = pSelf->GetPlayerChar(Victim);
if(!chr) if(!pChr)
return; return;
if(pSelf->m_apPlayers[Victim]) if(pSelf->m_apPlayers[Victim])
{ {
chr->Freeze(((time!=0&&time!=-1)?(pSelf->Server()->TickSpeed()*time):(-1))); pChr->Freeze(Seconds);
chr->m_pPlayer->m_RconFreeze = true; pChr->m_pPlayer->m_RconFreeze = Seconds != -2;
CServer* pServ = (CServer*)pSelf->Server(); 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); 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; CGameContext *pSelf = (CGameContext *)pUserData;
int Victim = pResult->GetVictim(); int Victim = pResult->GetVictim();
static bool Warning = false;
char buf[128]; char buf[128];
CCharacter* chr = pSelf->GetPlayerChar(Victim); CCharacter* pChr = pSelf->GetPlayerChar(Victim);
if(!chr) if(!pChr)
return; return;
chr->m_FreezeTime=2; if(pChr->m_DeepFreeze && !Warning)
chr->m_pPlayer->m_RconFreeze = false; {
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(); CServer* pServ = (CServer*)pSelf->Server();
str_format(buf, sizeof(buf), "'%s' ClientId=%d has been defrosted.", pServ->ClientName(ClientId), Victim); str_format(buf, sizeof(buf), "'%s' ClientId=%d has been defrosted.", pServ->ClientName(ClientId), Victim);
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "info", buf); pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "info", buf);

View file

@ -47,7 +47,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS)
// Character, "physical" m_pPlayer's part // Character, "physical" m_pPlayer's part
CCharacter::CCharacter(CGameWorld *pWorld) CCharacter::CCharacter(CGameWorld *pWorld)
: CEntity(pWorld, NETOBJTYPE_CHARACTER) : CEntity(pWorld, CGameWorld::ENTTYPE_CHARACTER)
{ {
m_ProximityRadius = ms_PhysSize; m_ProximityRadius = ms_PhysSize;
m_Health = 0; m_Health = 0;
@ -95,10 +95,14 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
if(m_pPlayer->m_RconFreeze) Freeze(-1); if(m_pPlayer->m_RconFreeze) Freeze(-1);
GameServer()->m_pController->OnCharacterSpawn(this); GameServer()->m_pController->OnCharacterSpawn(this);
if(GetPlayer()->m_IsUsingDDRaceClient) { if(GetPlayer()->m_IsUsingDDRaceClient)
{
Controller->m_Teams.SendTeamsState(GetPlayer()->GetCID()); 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_DefEmote = EMOTE_NORMAL;
m_DefEmoteReset = -1; m_DefEmoteReset = -1;
return true; return true;
@ -120,7 +124,7 @@ void CCharacter::SetWeapon(int W)
m_LastWeapon = m_ActiveWeapon; m_LastWeapon = m_ActiveWeapon;
m_QueuedWeapon = -1; m_QueuedWeapon = -1;
m_ActiveWeapon = W; 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) if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS)
m_ActiveWeapon = 0; m_ActiveWeapon = 0;
@ -186,11 +190,11 @@ void CCharacter::HandleNinja()
// check if we Hit anything along the way // check if we Hit anything along the way
{ {
CCharacter *aEnts[64]; CCharacter *aEnts[MAX_CLIENTS];
vec2 Dir = m_Pos - OldPos; vec2 Dir = m_Pos - OldPos;
float Radius = m_ProximityRadius * 2.0f; float Radius = m_ProximityRadius * 2.0f;
vec2 Center = OldPos + Dir * 0.5f; vec2 Center = OldPos + Dir * 0.5f;
int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, 64, NETOBJTYPE_CHARACTER); int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
for (int i = 0; i < Num; ++i) for (int i = 0; i < Num; ++i)
{ {
@ -212,7 +216,7 @@ void CCharacter::HandleNinja()
continue; continue;
// Hit a m_pPlayer, give him damage and stuffs... // Hit a m_pPlayer, give him damage and stuffs...
GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT, Teams()->TeamMask(Team()));
// set his velocity to fast upward (for now) // set his velocity to fast upward (for now)
if(m_NumObjectsHit < 10) if(m_NumObjectsHit < 10)
m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; m_apHitObjects[m_NumObjectsHit++] = aEnts[i];
@ -313,7 +317,7 @@ void CCharacter::FireWeapon()
if(m_PainSoundTimer<=0) if(m_PainSoundTimer<=0)
{ {
m_PainSoundTimer = 1 * Server()->TickSpeed(); 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; return;
} }
@ -329,39 +333,43 @@ void CCharacter::FireWeapon()
if (!g_Config.m_SvHit) break; if (!g_Config.m_SvHit) break;
CCharacter *aEnts[64]; CCharacter *apEnts[MAX_CLIENTS];
int Hits = 0; int Hits = 0;
int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)aEnts, int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
64, NETOBJTYPE_CHARACTER); MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
for (int i = 0; i < Num; ++i) for (int i = 0; i < Num; ++i)
{ {
CCharacter *Target = aEnts[i]; CCharacter *pTarget = apEnts[i];
//for DDRace mod or any other mod, which needs hammer hits through the wall remove second condition if ((pTarget == this || !CanCollide(pTarget->GetPlayer()->GetCID())) /*|| GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)*/)
if ((Target == this || !CanCollide(Target->GetPlayer()->GetCID())) /*|| GameServer()->Collision()->IntersectLine(ProjStartPos, Target->m_Pos, NULL, NULL)*/)
continue; continue;
// set his velocity to fast upward (for now) // set his velocity to fast upward (for now)
GameServer()->CreateHammerHit(m_Pos, Teams()->TeamMask(Team())); if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
aEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); 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; vec2 Dir;
if (length(Target->m_Pos - m_Pos) > 0.0f) if (length(pTarget->m_Pos - m_Pos) > 0.0f)
Dir = normalize(Target->m_Pos - m_Pos); Dir = normalize(pTarget->m_Pos - m_Pos);
else else
Dir = vec2(0.f, -1.f); Dir = vec2(0.f, -1.f);
vec2 Temp = Target->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f * (m_HammerType + 1);
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; Temp.x = 0;
if(Temp.x < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_90) || (Target->m_TileIndexR == TILE_STOP && Target->m_TileFlagsR == ROTATION_90) || (Target->m_TileIndexR == TILE_STOPS && (Target->m_TileFlagsR == ROTATION_90 || Target->m_TileFlagsR == ROTATION_270)) || (Target->m_TileIndexR == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOP && Target->m_TileFFlagsR == ROTATION_90) || (Target->m_TileFIndexR == TILE_STOPS && (Target->m_TileFFlagsR == ROTATION_90 || Target->m_TileFFlagsR == ROTATION_270)) || (Target->m_TileFIndexR == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOP && Target->m_TileSFlagsR == ROTATION_90) || (Target->m_TileSIndexR == TILE_STOPS && (Target->m_TileSFlagsR == ROTATION_90 || Target->m_TileSFlagsR == ROTATION_270)) || (Target->m_TileSIndexR == TILE_STOPA))) if(Temp.x < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOP && pTarget->m_TileFlagsR == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOPS && (pTarget->m_TileFlagsR == ROTATION_90 || pTarget->m_TileFlagsR == ROTATION_270)) || (pTarget->m_TileIndexR == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOP && pTarget->m_TileFFlagsR == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOPS && (pTarget->m_TileFFlagsR == ROTATION_90 || pTarget->m_TileFFlagsR == ROTATION_270)) || (pTarget->m_TileFIndexR == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOP && pTarget->m_TileSFlagsR == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOPS && (pTarget->m_TileSFlagsR == ROTATION_90 || pTarget->m_TileSFlagsR == ROTATION_270)) || (pTarget->m_TileSIndexR == TILE_STOPA)))
Temp.x = 0; Temp.x = 0;
if(Temp.y < 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_180) || (Target->m_TileIndexB == TILE_STOP && Target->m_TileFlagsB == ROTATION_180) || (Target->m_TileIndexB == TILE_STOPS && (Target->m_TileFlagsB == ROTATION_0 || Target->m_TileFlagsB == ROTATION_180)) || (Target->m_TileIndexB == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOP && Target->m_TileFFlagsB == ROTATION_180) || (Target->m_TileFIndexB == TILE_STOPS && (Target->m_TileFFlagsB == ROTATION_0 || Target->m_TileFFlagsB == ROTATION_180)) || (Target->m_TileFIndexB == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOP && Target->m_TileSFlagsB == ROTATION_180) || (Target->m_TileSIndexB == TILE_STOPS && (Target->m_TileSFlagsB == ROTATION_0 || Target->m_TileSFlagsB == ROTATION_180)) || (Target->m_TileSIndexB == TILE_STOPA))) if(Temp.y < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOP && pTarget->m_TileFlagsB == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOPS && (pTarget->m_TileFlagsB == ROTATION_0 || pTarget->m_TileFlagsB == ROTATION_180)) || (pTarget->m_TileIndexB == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOP && pTarget->m_TileFFlagsB == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOPS && (pTarget->m_TileFFlagsB == ROTATION_0 || pTarget->m_TileFFlagsB == ROTATION_180)) || (pTarget->m_TileFIndexB == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOP && pTarget->m_TileSFlagsB == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOPS && (pTarget->m_TileSFlagsB == ROTATION_0 || pTarget->m_TileSFlagsB == ROTATION_180)) || (pTarget->m_TileSIndexB == TILE_STOPA)))
Temp.y = 0; Temp.y = 0;
if(Temp.y > 0 && ((Target->m_TileIndex == TILE_STOP && Target->m_TileFlags == ROTATION_0) || (Target->m_TileIndexT == TILE_STOP && Target->m_TileFlagsT == ROTATION_0) || (Target->m_TileIndexT == TILE_STOPS && (Target->m_TileFlagsT == ROTATION_0 || Target->m_TileFlagsT == ROTATION_180)) || (Target->m_TileIndexT == TILE_STOPA) || (Target->m_TileFIndex == TILE_STOP && Target->m_TileFFlags == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOP && Target->m_TileFFlagsT == ROTATION_0) || (Target->m_TileFIndexT == TILE_STOPS && (Target->m_TileFFlagsT == ROTATION_0 || Target->m_TileFFlagsT == ROTATION_180)) || (Target->m_TileFIndexT == TILE_STOPA) || (Target->m_TileSIndex == TILE_STOP && Target->m_TileSFlags == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOP && Target->m_TileSFlagsT == ROTATION_0) || (Target->m_TileSIndexT == TILE_STOPS && (Target->m_TileSFlagsT == ROTATION_0 || Target->m_TileSFlagsT == ROTATION_180)) || (Target->m_TileSIndexT == TILE_STOPA))) if(Temp.y > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOP && pTarget->m_TileFlagsT == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOPS && (pTarget->m_TileFlagsT == ROTATION_0 || pTarget->m_TileFlagsT == ROTATION_180)) || (pTarget->m_TileIndexT == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOP && pTarget->m_TileFFlagsT == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOPS && (pTarget->m_TileFFlagsT == ROTATION_0 || pTarget->m_TileFFlagsT == ROTATION_180)) || (pTarget->m_TileFIndexT == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOP && pTarget->m_TileSFlagsT == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOPS && (pTarget->m_TileSFlagsT == ROTATION_0 || pTarget->m_TileSFlagsT == ROTATION_180)) || (pTarget->m_TileSIndexT == TILE_STOPA)))
Temp.y = 0; Temp.y = 0;
Target->m_Core.m_Vel = Temp; Temp -= pTarget->m_Core.m_Vel;
Target->UnFreeze(); 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++; Hits++;
} }
@ -373,7 +381,7 @@ void CCharacter::FireWeapon()
case WEAPON_GUN: case WEAPON_GUN:
{ {
CProjectile *Proj = new CProjectile CProjectile *pProj = new CProjectile
( (
GameWorld(), GameWorld(),
WEAPON_GUN,//Type WEAPON_GUN,//Type
@ -390,7 +398,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1); Msg.AddInt(1);
@ -405,7 +413,7 @@ void CCharacter::FireWeapon()
case WEAPON_SHOTGUN: case WEAPON_SHOTGUN:
{ {
new CLaser(&GameServer()->m_World, m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID(), 1); 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; /*int ShotSpread = 2;
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
@ -418,7 +426,7 @@ void CCharacter::FireWeapon()
a += Spreading[i+2]; a += Spreading[i+2];
float v = 1-(absolute(i)/(float)ShotSpread); float v = 1-(absolute(i)/(float)ShotSpread);
float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v); float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
CProjectile *Proj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
m_pPlayer->GetCID(), m_pPlayer->GetCID(),
ProjStartPos, ProjStartPos,
vec2(cosf(a), sinf(a))*Speed, vec2(cosf(a), sinf(a))*Speed,
@ -427,7 +435,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]); Msg.AddInt(((int *)&p)[i]);
@ -440,7 +448,7 @@ void CCharacter::FireWeapon()
case WEAPON_GRENADE: case WEAPON_GRENADE:
{ {
CProjectile *Proj = new CProjectile CProjectile *pProj = new CProjectile
( (
GameWorld(), GameWorld(),
WEAPON_GRENADE,//Type WEAPON_GRENADE,//Type
@ -457,7 +465,7 @@ void CCharacter::FireWeapon()
// pack the Projectile and send it to the client Directly // pack the Projectile and send it to the client Directly
CNetObj_Projectile p; CNetObj_Projectile p;
Proj->FillInfo(&p); pProj->FillInfo(&p);
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1); Msg.AddInt(1);
@ -557,7 +565,7 @@ bool CCharacter::GiveWeapon(int Weapon, int Ammo)
void CCharacter::GiveNinja() void CCharacter::GiveNinja()
{ {
if(!m_aWeapons[WEAPON_NINJA].m_Got) 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_Ninja.m_ActivationTick = Server()->Tick();
m_aWeapons[WEAPON_NINJA].m_Got = true; m_aWeapons[WEAPON_NINJA].m_Got = true;
if (!m_FreezeTime) m_aWeapons[WEAPON_NINJA].m_Ammo = -1; if (!m_FreezeTime) m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
@ -731,8 +739,6 @@ void CCharacter::HandleFly()
void CCharacter::Tick() 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) /*if(m_pPlayer->m_ForceBalanced)
{ {
char Buf[128]; char Buf[128];
@ -741,7 +747,7 @@ void CCharacter::Tick()
m_pPlayer->m_ForceBalanced = false; 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) if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0)
m_LastMove = Server()->Tick(); m_LastMove = Server()->Tick();
@ -749,9 +755,9 @@ void CCharacter::Tick()
{ {
if (m_FreezeTime % Server()->TickSpeed() == 0 || m_FreezeTime == -1) 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--; m_FreezeTime--;
else else
m_Ninja.m_ActivationTick = Server()->Tick(); m_Ninja.m_ActivationTick = Server()->Tick();
@ -760,13 +766,15 @@ void CCharacter::Tick()
m_Input.m_Hook = 0; m_Input.m_Hook = 0;
//m_Input.m_Fire = 0; //m_Input.m_Fire = 0;
if (m_FreezeTime == 1) { if (m_FreezeTime == 1)
{
UnFreeze(); UnFreeze();
m_pPlayer->m_RconFreeze = false;
} }
} }
m_Core.m_Input = m_Input; m_Core.m_Input = m_Input;
m_Core.Tick(true);
m_Core.m_Id = GetPlayer()->GetCID(); m_Core.m_Id = GetPlayer()->GetCID();
m_Core.Tick(true);
if (m_DefEmoteReset >= 0 && m_DefEmoteReset <= Server()->Tick()) if (m_DefEmoteReset >= 0 && m_DefEmoteReset <= Server()->Tick())
{ {
@ -774,16 +782,15 @@ void CCharacter::Tick()
m_EmoteType = m_DefEmote = EMOTE_NORMAL; m_EmoteType = m_DefEmote = EMOTE_NORMAL;
m_EmoteStop = -1; m_EmoteStop = -1;
} }
m_DoSplash = false; 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; m_Core.m_HookTick = 0;
if (m_DeepFreeze && !m_Super)
Freeze();
if (m_Super && m_Core.m_Jumped > 1) if (m_Super && m_Core.m_Jumped > 1)
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]; char aBroadcast[128];
m_Time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed()); m_Time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed());
CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID()); CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID());
@ -840,20 +847,86 @@ void CCharacter::Tick()
} }
m_RefreshTime = Server()->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()) if(!Indices.empty())
for(std::list < int >::iterator i = Indices.begin(); i != Indices.end(); i++) for(std::list < int >::iterator i = Indices.begin(); i != Indices.end(); i++)
HandleTiles(*i); HandleTiles(*i);
else else
HandleTiles(GameServer()->Collision()->GetPureMapIndex(m_Pos)); HandleTiles(CurrentIndex);
// handle speedup tiles
// kill player when leaving gamelayer if(GameServer()->Collision()->IsSpeedup(CurrentIndex))
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)
{ {
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 // handle Weapons
HandleWeapons(); HandleWeapons();
@ -874,7 +947,7 @@ void CCharacter::HandleTiles(int Index)
{//dbg_msg("num","%d",++num); {//dbg_msg("num","%d",++num);
CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController; CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;
int MapIndex = Index; int MapIndex = Index;
int PureMapIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos); //int PureMapIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos);
float Offset = 4; float Offset = 4;
int MapIndexL = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x + (m_ProximityRadius/2)+Offset,m_Pos.y)); 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)); 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()))) 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; bool CanBegin = true;
if(g_Config.m_SvTeam == 1 && (Team() == TEAM_FLOCK || Teams()->Count(Team()) <= 1) ) { 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 GameServer()->SendChatTarget(GetPlayer()->GetCID(),"I already told you too join a team");
CanBegin = false; CanBegin = false;
} }
if(CanBegin) { if(CanBegin) {
@ -997,14 +1070,39 @@ void CCharacter::HandleTiles(int Index)
{ {
Controller->m_Teams.OnCharacterFinish(m_pPlayer->GetCID()); 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(); 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(((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) 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_EndTick[Team()] = 0;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHCLOSE; GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHCLOSE;
} }
// handle speedup tiles else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER)
if(GameServer()->Collision()->IsSpeedup(PureMapIndex) == TILE_BOOST)
{ {
vec2 Direction, MaxVel, TempVel = m_Core.m_Vel; Freeze(GameServer()->Collision()->GetSwitchDelay(MapIndex));
int Force, MaxSpeed = 0; }
float TeeAngle, SpeederAngle, DiffAngle, SpeedLeft, TeeSpeed; else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
GameServer()->Collision()->GetSpeedup(MapIndex, &Direction, &Force, &MaxSpeed); {
if(Force == 255 && MaxSpeed) m_DeepFreeze = true;
{ }
m_Core.m_Vel = Direction * (MaxSpeed/5); else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
} {
else m_DeepFreeze = false;
{
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);
}
} }
m_LastBooster = MapIndex;
int z = GameServer()->Collision()->IsTeleport(MapIndex); int z = GameServer()->Collision()->IsTeleport(MapIndex);
if(z && ((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts[z-1].size()) 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); m_Core.m_Vel = vec2(0,0);
return; return;
} }
// handle death-tiles // handle death-tiles and leaving gamelayer
if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH)&& GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameLayerClipped(m_Pos)) &&
!m_Super) !m_Super)
{ {
Die(m_pPlayer->GetCID(), WEAPON_WORLD); Die(m_pPlayer->GetCID(), WEAPON_WORLD);
@ -1266,13 +1296,13 @@ void CCharacter::TickDefered()
} }
int Events = m_Core.m_TriggeredEvents; 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_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, Mask); 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, Mask); if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Teams()->TeamMask(Team()));
if(m_pPlayer->GetTeam() == TEAM_SPECTATORS) 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; return false;
if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed()) if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
{ {
for(int i=0;i<NUM_WEAPONS;i++) for(int i = 0; i < NUM_WEAPONS; i++)
if(m_aWeapons[i].m_Got) if(m_aWeapons[i].m_Got)
{ {
m_aWeapons[i].m_Ammo = 0; m_aWeapons[i].m_Ammo = 0;
} }
m_Armor=0; m_Armor = 0;
m_FreezeTime=Time; m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed();
m_FreezeTick=Server()->Tick(); m_FreezeTick = Server()->Tick();
return true; return true;
} }
return false; return false;
@ -1322,28 +1352,12 @@ bool CCharacter::Freeze(int Time)
bool CCharacter::Freeze() bool CCharacter::Freeze()
{ {
int Time = Server()->TickSpeed()*3; return Freeze(g_Config.m_SvFreezeDelay);
if (Time <= 1 || m_Super || m_FreezeTime == -1)
return false;
if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed())
{
for(int i=0;i<NUM_WEAPONS;i++)
if(m_aWeapons[i].m_Got)
{
m_aWeapons[i].m_Ammo = 0;
}
m_Armor=0;
m_Ninja.m_ActivationTick = Server()->Tick();
m_FreezeTime=Time;
m_FreezeTick=Server()->Tick();
return true;
}
return false;
} }
bool CCharacter::UnFreeze() bool CCharacter::UnFreeze()
{ {
if (m_FreezeTime>0) if (m_FreezeTime > 0)
{ {
m_Armor=10; m_Armor=10;
for(int i=0;i<NUM_WEAPONS;i++) for(int i=0;i<NUM_WEAPONS;i++)
@ -1408,7 +1422,7 @@ void CCharacter::Die(int Killer, int Weapon)
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1); Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
// a nice sound // 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 // this is for auto respawn after 3 secs
m_pPlayer->m_DieTick = Server()->Tick(); m_pPlayer->m_DieTick = Server()->Tick();

View file

@ -122,6 +122,9 @@ public:
//DDRace //DDRace
int m_FreezeTime; int m_FreezeTime;
int m_FreezeTick; int m_FreezeTick;
bool m_DeepFreeze;
bool m_EndlessHook;
int m_Doored; int m_Doored;
@ -178,7 +181,6 @@ public:
int m_StartTime; int m_StartTime;
int m_RefreshTime; int m_RefreshTime;
int m_LastBooster;
vec2 m_PrevPos; vec2 m_PrevPos;
// checkpoints // checkpoints

View file

@ -6,7 +6,7 @@
#include "door.h" #include "door.h"
CDoor::CDoor(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length, int Number) 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_Number = Number;
m_Pos = Pos; m_Pos = Pos;
@ -30,7 +30,11 @@ void CDoor::ResetCollision()
{ {
for(int i=0;i<m_Length-1;i++) for(int i=0;i<m_Length-1;i++)
{ {
GameServer()->Collision()->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);
} }
} }

View file

@ -12,7 +12,7 @@
const int LENGTH=700; const int LENGTH=700;
CDragger::CDragger(CGameWorld *pGameWorld, vec2 Pos, float Strength, bool NW, int CatchedTeam, int Layer, int Number) 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_Layer = Layer;
m_Number = Number; m_Number = Number;
@ -31,7 +31,7 @@ void CDragger::Move()
if(m_Target) if(m_Target)
return; return;
CCharacter *Ents[16]; 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 Id=-1;
int MinLen=0; int MinLen=0;
for (int i = 0; i < Num; i++) for (int i = 0; i < Num; i++)
@ -97,7 +97,7 @@ void CDragger::Tick()
{ {
int Flags; int Flags;
m_EvalTick=Server()->Tick(); 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) if (index)
{ {
m_Core=GameServer()->Collision()->CpSpeed(index, Flags); m_Core=GameServer()->Collision()->CpSpeed(index, Flags);

View file

@ -5,7 +5,7 @@
#include "flag.h" #include "flag.h"
CFlag::CFlag(CGameWorld *pGameWorld, int Team) CFlag::CFlag(CGameWorld *pGameWorld, int Team)
: CEntity(pGameWorld, NETOBJTYPE_FLAG) : CEntity(pGameWorld, CGameWorld::ENTTYPE_FLAG)
{ {
m_Team = Team; m_Team = Team;
m_ProximityRadius = ms_PhysSize; m_ProximityRadius = ms_PhysSize;

View file

@ -13,7 +13,7 @@ const int RANGE=700;
// CGun // CGun
////////////////////////////////////////////////// //////////////////////////////////////////////////
CGun::CGun(CGameWorld *pGameWorld, vec2 Pos, bool Freeze, bool Explosive, int Layer, int Number) 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_Layer = Layer;
m_Number = Number; m_Number = Number;
@ -38,7 +38,7 @@ void CGun::Fire()
} }
int Num = -1; 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++) for (int i = 0; i < Num; i++)
{ {
@ -77,7 +77,7 @@ void CGun::Tick()
{ {
int Flags; int Flags;
m_EvalTick=Server()->Tick(); 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) if (index)
{ {
m_Core=GameServer()->Collision()->CpSpeed(index, Flags); m_Core=GameServer()->Collision()->CpSpeed(index, Flags);

View file

@ -6,7 +6,7 @@
#include "laser.h" #include "laser.h"
CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner, int Type) 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_Pos = Pos;
m_Owner = Owner; m_Owner = Owner;

View file

@ -13,7 +13,7 @@
CLight::CLight(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length, int Layer, int Number) 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_Layer = Layer;
m_Number = Number; m_Number = Number;
@ -34,7 +34,7 @@ bool CLight::HitCharacter()
for(std::list < CCharacter * >::iterator i = HitCharacters.begin(); i != HitCharacters.end(); i++) { for(std::list < CCharacter * >::iterator i = HitCharacters.begin(); i != HitCharacters.end(); i++) {
CCharacter * Char = *i; CCharacter * Char = *i;
if(m_Layer == LAYER_SWITCH && !GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[Char->Team()]) continue; 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; return true;
} }
@ -86,7 +86,7 @@ void CLight::Tick()
{ {
int Flags; int Flags;
m_EvalTick=Server()->Tick(); 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) if (index)
{ {
m_Core=GameServer()->Collision()->CpSpeed(index, Flags); m_Core=GameServer()->Collision()->CpSpeed(index, Flags);

View file

@ -5,7 +5,7 @@
#include "pickup.h" #include "pickup.h"
CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int Number) 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_Layer = Layer;
m_Number = Number; m_Number = Number;
@ -33,7 +33,7 @@ void CPickup::Move()
if (Server()->Tick()%int(Server()->TickSpeed() * 0.15f) == 0) if (Server()->Tick()%int(Server()->TickSpeed() * 0.15f) == 0)
{ {
int Flags; 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) if (index)
{ {
m_Core=GameServer()->Collision()->CpSpeed(index, Flags); m_Core=GameServer()->Collision()->CpSpeed(index, Flags);
@ -61,7 +61,7 @@ void CPickup::Tick()
}*/ }*/
// Check if a player intersected us // Check if a player intersected us
CCharacter *apEnts[MAX_CLIENTS]; 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) { for(int i = 0; i < Num; ++i) {
CCharacter * pChr = apEnts[i]; CCharacter * pChr = apEnts[i];
if(pChr && pChr->IsAlive()) if(pChr && pChr->IsAlive())
@ -121,16 +121,21 @@ void CPickup::Tick()
} }
break; 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<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER));
for(; pC; pC = (CCharacter *)pC->TypeNext())
{ {
// activate ninja on target player if (pC != pChr)
//if(!pChr->m_FreezeTime) pChr->GiveNinja(); pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed());
pChr->GiveNinja(); }*/
//RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; break;
}
break;
}
default: default:
break; break;
}; };

View file

@ -14,7 +14,7 @@ const float ACCEL=1.1f;
////////////////////////////////////////////////// //////////////////////////////////////////////////
CPlasma::CPlasma(CGameWorld *pGameWorld, vec2 Pos, vec2 Dir, bool Freeze, bool Explosive, int ResponsibleTeam) 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_Pos = Pos;
m_Core = Dir; m_Core = Dir;
@ -34,7 +34,7 @@ bool CPlasma::HitCharacter()
return false; return false;
if(Hit->Team() != m_ResponsibleTeam) 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) if(m_Explosive)
GameServer()->CreateExplosion(m_Pos, -1, WEAPON_GRENADE, true, m_ResponsibleTeam, Hit->Teams()->TeamMask(m_ResponsibleTeam)); GameServer()->CreateExplosion(m_Pos, -1, WEAPON_GRENADE, true, m_ResponsibleTeam, Hit->Teams()->TeamMask(m_ResponsibleTeam));
GameServer()->m_World.DestroyEntity(this); GameServer()->m_World.DestroyEntity(this);

View file

@ -22,7 +22,7 @@ CProjectile::CProjectile
int Layer, int Layer,
int Number int Number
) )
: CEntity(pGameWorld, NETOBJTYPE_PROJECTILE) : CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE)
{ {
m_Layer = Layer; m_Layer = Layer;
m_Number = Number; m_Number = Number;
@ -120,7 +120,7 @@ void CProjectile::Tick()
{ {
TeamMask = OwnerChar->Teams()->TeamMask( OwnerChar->Team()); TeamMask = OwnerChar->Teams()->TeamMask( OwnerChar->Team());
} }
if( ((TargetChr && (g_Config.m_SvHit || m_Owner == -1 || TargetChr == OwnerChar)) || Collide) && !isWeaponCollide)//TODO:TEAM if( ((TargetChr && (g_Config.m_SvHit || m_Owner == -1 || TargetChr == OwnerChar)) || Collide || GameLayerClipped(CurPos)) && !isWeaponCollide)//TODO:TEAM
{ {
if(m_Explosive/*??*/ && (!TargetChr || (TargetChr && !m_Freeze))) if(m_Explosive/*??*/ && (!TargetChr || (TargetChr && !m_Freeze)))
{ {
@ -130,7 +130,7 @@ void CProjectile::Tick()
(m_Owner != -1)? TeamMask : -1); (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)) 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) if(Collide && m_Bouncing != 0)
{ {
m_StartTick = Server()->Tick(); m_StartTick = Server()->Tick();

View file

@ -11,15 +11,13 @@ CEntity::CEntity(CGameWorld *pGameWorld, int ObjType)
{ {
m_pGameWorld = pGameWorld; m_pGameWorld = pGameWorld;
m_Objtype = ObjType; m_ObjType = ObjType;
m_Pos = vec2(0,0); m_Pos = vec2(0,0);
m_ProximityRadius = 0; m_ProximityRadius = 0;
m_MarkedForDestroy = false; m_MarkedForDestroy = false;
m_Id = Server()->SnapNewID(); m_Id = Server()->SnapNewID();
m_pNextEntity = 0;
m_pPrevEntity = 0;
m_pPrevTypeEntity = 0; m_pPrevTypeEntity = 0;
m_pNextTypeEntity = 0; m_pNextTypeEntity = 0;
} }
@ -50,3 +48,9 @@ int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos)
return 1; return 1;
return 0; return 0;
} }
bool CEntity::GameLayerClipped(vec2 CheckPos)
{
return round(CheckPos.x)/32 < -200 || round(CheckPos.x)/32 > GameServer()->Collision()->GetWidth()+200 ||
round(CheckPos.y)/32 < -200 || round(CheckPos.y)/32 > GameServer()->Collision()->GetHeight()+200 ? true : false;
}

View file

@ -57,11 +57,8 @@
class CEntity class CEntity
{ {
MACRO_ALLOC_HEAP() 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_pPrevTypeEntity;
CEntity *m_pNextTypeEntity; CEntity *m_pNextTypeEntity;
@ -69,7 +66,7 @@ private:
protected: protected:
bool m_MarkedForDestroy; bool m_MarkedForDestroy;
int m_Id; int m_Id;
int m_Objtype; int m_ObjType;
int m_Number; int m_Number;
int m_Layer; int m_Layer;
public: public:
@ -143,7 +140,8 @@ public:
*/ */
int NetworkClipped(int SnappingClient); int NetworkClipped(int SnappingClient);
int NetworkClipped(int SnappingClient, vec2 CheckPos); int NetworkClipped(int SnappingClient, vec2 CheckPos);
bool GameLayerClipped(vec2 CheckPos);
/* /*
Variable: proximity_radius Variable: proximity_radius

View file

@ -138,10 +138,10 @@ void CGameContext::CreateExplosion(vec2 P, int Owner, int Weapon, bool NoDamage,
/*if(!NoDamage) /*if(!NoDamage)
{*/ {*/
// deal damage // deal damage
CCharacter *apEnts[64]; CCharacter *apEnts[MAX_CLIENTS];
float Radius = 135.0f; float Radius = 135.0f;
float InnerRadius = 48.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++) for(int i = 0; i < Num; i++)
{ {
vec2 Diff = apEnts[i]->m_Pos - P; 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); Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i);
} }
} else { } 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); 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; 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; m_apPlayers[ClientId]->m_Score = (Score()->PlayerData(ClientId)->m_BestTime)?Score()->PlayerData(ClientId)->m_BestTime:-9999;
char aBuf[512]; if(((CServer *) Server())->m_aPrevStates[ClientId] < CServer::CClient::STATE_INGAME)
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); char aBuf[512];
str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientId), m_pController->GetTeamName(m_apPlayers[ClientId]->GetTeam()));
SendChatTarget(ClientId, "DDRace Mod. Version: " DDRACE_VERSION); SendChat(-1, CGameContext::CHAT_ALL, aBuf);
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); SendChatTarget(ClientId, "DDRace Mod. Version: " DDRACE_VERSION);
//str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientId, Server()->ClientName(ClientId), m_apPlayers[ClientId]->GetTeam()); 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; m_VoteUpdate = true;
} }
@ -763,7 +766,7 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
//if(Team) //if(Team)
int GameTeam = ((CGameControllerDDRace*)m_pController)->m_Teams.m_Core.Team(p->GetCID()); int GameTeam = ((CGameControllerDDRace*)m_pController)->m_Teams.m_Core.Team(p->GetCID());
if(Team) { if(Team) {
Team = (p->GetTeam() == -1) ? CHAT_SPEC : (GameTeam == 0 ? CHAT_ALL : GameTeam); Team = ((p->GetTeam() == -1) ? CHAT_SPEC : GameTeam);
} else { } else {
Team = CHAT_ALL; 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(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); //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)) 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); 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) void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData, int ClientID)
{ {
CGameContext *pSelf = (CGameContext *)pUserData; 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("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("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("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", "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); Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Resets all tuning", 4);

View file

@ -56,10 +56,12 @@ class CGameContext : public IGameServer
static void ConSetTeam(IConsole::IResult *pResult, void *pUserData, int ClientId); static void ConSetTeam(IConsole::IResult *pResult, void *pUserData, int ClientId);
static void ConSetTeamAll(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 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 ConVote(IConsole::IResult *pResult, void *pUserData, int ClientId);
static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); 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 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 ConLogOut(IConsole::IResult *pResult, void *pUserData, int ClientId);
static void ConSetlvl1(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); 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 ConMove(IConsole::IResult *pResult, void *pUserData, int ClientId);
static void ConMoveRaw(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 ConInvisMe(IConsole::IResult *pResult, void *pUserData, int ClientId);
static void ConVisMe(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); 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<<ClientId; } inline int CmaskOne(int ClientId) { return 1<<ClientId; }
inline int CmaskAllExceptOne(int ClientId) { return 0x7fffffff^CmaskOne(ClientId); } inline int CmaskAllExceptOne(int ClientId) { return 0x7fffffff^CmaskOne(ClientId); }
inline bool CmaskIsSet(int Mask, int ClientId) { return (Mask&CmaskOne(ClientId)) != 0; } inline bool CmaskIsSet(int Mask, int ClientId) { return (Mask&CmaskOne(ClientId)) != 0; }
#endif #endif

View file

@ -57,7 +57,7 @@ IGameController::~IGameController()
float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos)
{ {
float Score = 0.0f; float Score = 0.0f;
CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER)); CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER));
for(; pC; pC = (CCharacter *)pC->TypeNext()) for(; pC; pC = (CCharacter *)pC->TypeNext())
{ {
// team mates are not as dangerous as enemies // team mates are not as dangerous as enemies
@ -66,10 +66,7 @@ float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos)
Scoremod = 0.5f; Scoremod = 0.5f;
float d = distance(Pos, pC->m_Pos); float d = distance(Pos, pC->m_Pos);
if(d == 0) Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d);
Score += 1000000000.0f;
else
Score += 1.0f/d;
} }
return Score; return Score;
@ -840,7 +837,7 @@ bool IGameController::CheckTeamBalance()
char aBuf[256]; char aBuf[256];
if(absolute(aT[0]-aT[1]) >= 2) 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); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
if(GameServer()->m_pController->m_UnbalancedTick == -1) if(GameServer()->m_pController->m_UnbalancedTick == -1)
GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); GameServer()->m_pController->m_UnbalancedTick = Server()->Tick();
@ -848,7 +845,7 @@ bool IGameController::CheckTeamBalance()
} }
else 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()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
GameServer()->m_pController->m_UnbalancedTick = -1; GameServer()->m_pController->m_UnbalancedTick = -1;
return true; return true;

View file

@ -92,8 +92,8 @@ void CGameControllerCTF::Tick()
if(!F) if(!F)
continue; continue;
// flag hits death-tile, reset it // flag hits death-tile or left the game layer, reset it
if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH) if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH || F->GameLayerClipped(F->m_Pos))
{ {
GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN); GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
F->Reset(); F->Reset();
@ -140,7 +140,7 @@ void CGameControllerCTF::Tick()
else else
{ {
CCharacter *apCloseCCharacters[MAX_CLIENTS]; 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++) 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)) 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()
} }
} }
} }
*/ */

View file

@ -15,16 +15,16 @@ CGameWorld::CGameWorld()
m_Paused = false; m_Paused = false;
m_ResetRequested = false; m_ResetRequested = false;
m_pFirstEntity = 0x0; for(int i = 0; i < NUM_ENTTYPES; i++)
for(int i = 0; i < NUM_ENT_TYPES; i++)
m_apFirstEntityTypes[i] = 0; m_apFirstEntityTypes[i] = 0;
} }
CGameWorld::~CGameWorld() CGameWorld::~CGameWorld()
{ {
// delete all entities // delete all entities
while(m_pFirstEntity) for(int i = 0; i < NUM_ENTTYPES; i++)
delete m_pFirstEntity; while(m_apFirstEntityTypes[i])
delete m_apFirstEntityTypes[i];
} }
void CGameWorld::SetGameServer(CGameContext *pGameServer) void CGameWorld::SetGameServer(CGameContext *pGameServer)
@ -35,15 +35,16 @@ void CGameWorld::SetGameServer(CGameContext *pGameServer)
CEntity *CGameWorld::FindFirst(int Type) 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) int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type)
{ {
if(Type < 0 || Type >= NUM_ENTTYPES)
return 0;
int Num = 0; int Num = 0;
for(CEntity *pEnt = (Type<0) ? m_pFirstEntity : m_apFirstEntityTypes[Type]; for(CEntity *pEnt = m_apFirstEntityTypes[Type]; pEnt; pEnt = pEnt->m_pNextTypeEntity)
pEnt; pEnt = (Type<0) ? pEnt->m_pNextEntity : pEnt->m_pNextTypeEntity)
{ {
if(distance(pEnt->m_Pos, Pos) < Radius+pEnt->m_ProximityRadius) 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) void CGameWorld::InsertEntity(CEntity *pEnt)
{ {
CEntity *pCur = m_pFirstEntity; #ifdef CONF_DEBUG
while(pCur) for(CEntity *pCur = m_apFirstEntityTypes[pEnt->m_ObjType]; pCur; pCur = pCur->m_pNextTypeEntity)
{
dbg_assert(pCur != pEnt, "err"); dbg_assert(pCur != pEnt, "err");
pCur = pCur->m_pNextEntity; #endif
}
// insert it // insert it
if(m_pFirstEntity) if(m_apFirstEntityTypes[pEnt->m_ObjType])
m_pFirstEntity->m_pPrevEntity = pEnt; m_apFirstEntityTypes[pEnt->m_ObjType]->m_pPrevTypeEntity = pEnt;
pEnt->m_pNextEntity = m_pFirstEntity; pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_ObjType];
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];
pEnt->m_pPrevTypeEntity = 0x0; pEnt->m_pPrevTypeEntity = 0x0;
m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt; m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt;
} }
void CGameWorld::DestroyEntity(CEntity *pEnt) void CGameWorld::DestroyEntity(CEntity *pEnt)
@ -89,26 +81,21 @@ void CGameWorld::DestroyEntity(CEntity *pEnt)
void CGameWorld::RemoveEntity(CEntity *pEnt) void CGameWorld::RemoveEntity(CEntity *pEnt)
{ {
// not in the list // 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; return;
// remove // 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) if(pEnt->m_pPrevTypeEntity)
pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity; pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity;
else else
m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt->m_pNextTypeEntity; m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt->m_pNextTypeEntity;
if(pEnt->m_pNextTypeEntity) if(pEnt->m_pNextTypeEntity)
pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity; pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity;
pEnt->m_pNextEntity = 0; // keep list traversing valid
pEnt->m_pPrevEntity = 0; if(m_pNextTraverseEntity == pEnt)
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->m_pNextTypeEntity = 0; pEnt->m_pNextTypeEntity = 0;
pEnt->m_pPrevTypeEntity = 0; pEnt->m_pPrevTypeEntity = 0;
} }
@ -116,15 +103,25 @@ void CGameWorld::RemoveEntity(CEntity *pEnt)
// //
void CGameWorld::Snap(int SnappingClient) void CGameWorld::Snap(int SnappingClient)
{ {
for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) for(int i = 0; i < NUM_ENTTYPES; i++)
pEnt->Snap(SnappingClient); for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->Snap(SnappingClient);
pEnt = m_pNextTraverseEntity;
}
} }
void CGameWorld::Reset() void CGameWorld::Reset()
{ {
// reset all entities // reset all entities
for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) for(int i = 0; i < NUM_ENTTYPES; i++)
pEnt->Reset(); for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->Reset();
pEnt = m_pNextTraverseEntity;
}
RemoveEntities(); RemoveEntities();
GameServer()->m_pController->PostReset(); GameServer()->m_pController->PostReset();
@ -136,17 +133,17 @@ void CGameWorld::Reset()
void CGameWorld::RemoveEntities() void CGameWorld::RemoveEntities()
{ {
// destroy objects marked for destruction // destroy objects marked for destruction
CEntity *pEnt = m_pFirstEntity; for(int i = 0; i < NUM_ENTTYPES; i++)
while(pEnt) for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
{
CEntity *pNext = pEnt->m_pNextEntity;
if(pEnt->m_MarkedForDestroy)
{ {
RemoveEntity(pEnt); m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->Destroy(); if(pEnt->m_MarkedForDestroy)
{
RemoveEntity(pEnt);
pEnt->Destroy();
}
pEnt = m_pNextTraverseEntity;
} }
pEnt = pNext;
}
} }
void CGameWorld::Tick() void CGameWorld::Tick()
@ -159,11 +156,21 @@ void CGameWorld::Tick()
if(GameServer()->m_pController->IsForceBalanced()) if(GameServer()->m_pController->IsForceBalanced())
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced"); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
// update all objects // update all objects
for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) for(int i = 0; i < NUM_ENTTYPES; i++)
pEnt->Tick(); 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) for(int i = 0; i < NUM_ENTTYPES; i++)
pEnt->TickDefered(); for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->TickDefered();
pEnt = m_pNextTraverseEntity;
}
} }
RemoveEntities(); RemoveEntities();
@ -178,7 +185,7 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v
vec2 LineDir = normalize(Pos1-Pos0); vec2 LineDir = normalize(Pos1-Pos0);
CCharacter *pClosest = 0; CCharacter *pClosest = 0;
CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); CCharacter *p = (CCharacter *)FindFirst(ENTTYPE_CHARACTER);
for(; p; p = (CCharacter *)p->TypeNext()) for(; p; p = (CCharacter *)p->TypeNext())
{ {
if(p == pNotThis) if(p == pNotThis)
@ -208,7 +215,7 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotTh
float ClosestRange = Radius*2; float ClosestRange = Radius*2;
CCharacter *pClosest = 0; 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()) for(; p; p = (CCharacter *)p->TypeNext())
{ {
if(p == pNotThis) if(p == pNotThis)
@ -233,7 +240,7 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
// Find other players // Find other players
vec2 LineDir = normalize(Pos1-Pos0); vec2 LineDir = normalize(Pos1-Pos0);
CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); CCharacter *p = (CCharacter *)FindFirst(CGameWorld::ENTTYPE_CHARACTER);
for(; p; p = (CCharacter *)p->TypeNext()) for(; p; p = (CCharacter *)p->TypeNext())
{ {
if(p == pNotThis) if(p == pNotThis)
@ -252,7 +259,7 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
void CGameWorld::ReleaseHooked(int ClientId) 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()) for(; p; p = (CCharacter *)p->TypeNext())
if(p->m_Core.m_HookedPlayer == ClientId && !p->m_Super) 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_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
p->m_Core.m_HookState = HOOK_RETRACTED; p->m_Core.m_HookState = HOOK_RETRACTED;
} }
}
}

View file

@ -16,17 +16,23 @@ class CCharacter;
*/ */
class CGameWorld class CGameWorld
{ {
public:
enum
{
ENTTYPE_PROJECTILE = 0,
ENTTYPE_LASER,
ENTTYPE_PICKUP,
ENTTYPE_FLAG,
ENTTYPE_CHARACTER,
NUM_ENTTYPES
};
private:
void Reset(); void Reset();
void RemoveEntities(); void RemoveEntities();
enum CEntity *m_pNextTraverseEntity;
{ CEntity *m_apFirstEntityTypes[NUM_ENTTYPES];
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];
class CGameContext *m_pGameServer; class CGameContext *m_pGameServer;
class IServer *m_pServer; class IServer *m_pServer;
@ -44,7 +50,6 @@ public:
void SetGameServer(CGameContext *pGameServer); void SetGameServer(CGameContext *pGameServer);
CEntity *FindFirst() { return m_pFirstEntity; }
CEntity *FindFirst(int Type); CEntity *FindFirst(int Type);
/* /*
@ -57,12 +62,12 @@ public:
ents - Pointer to a list that should be filled with the pointers ents - Pointer to a list that should be filled with the pointers
to the entities. to the entities.
max - Number of entities that fits into the ents array. 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: Returns:
Number of entities found and added to the ents array. 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 Function: InterserctCharacters

View file

@ -1,11 +1,9 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* (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. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <new> #include <new>
//#include <stdio.h> //TODO:GFX check if linux still needs this #include <engine/shared/config.h>
#include <engine/server.h> #include <engine/server.h>
#include <engine/server/server.h> #include <engine/server/server.h>
#include <engine/shared/config.h>
#include "player.h" #include "player.h"
#include "gamecontext.h" #include "gamecontext.h"
#include <game/gamecore.h> #include <game/gamecore.h>
@ -46,7 +44,9 @@ CPlayer::~CPlayer()
void CPlayer::Tick() 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)) if(!Server()->ClientIngame(m_ClientID))
return; return;
@ -95,6 +95,9 @@ void CPlayer::Tick()
void CPlayer::Snap(int SnappingClient) 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)) if(!Server()->ClientIngame(m_ClientID))
return; return;
@ -240,7 +243,7 @@ void CPlayer::TryRespawn()
// check if the position is occupado // check if the position is occupado
CEntity *apEnts[2] = {0}; 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) if(NumEnts < 3)
{ {
m_Spawning = false; m_Spawning = false;
@ -285,6 +288,8 @@ void CPlayer::LoadCharacter()
Character->m_LastWeapon = m_PauseInfo.m_LastWeapon; Character->m_LastWeapon = m_PauseInfo.m_LastWeapon;
Character->m_HammerType = m_PauseInfo.m_HammerType; Character->m_HammerType = m_PauseInfo.m_HammerType;
Character->m_Super = m_PauseInfo.m_Super; 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; CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;
Controller->m_Teams.m_Core.Team(GetCID(), m_PauseInfo.m_Team); Controller->m_Teams.m_Core.Team(GetCID(), m_PauseInfo.m_Team);
m_PauseInfo.m_Respawn = false; m_PauseInfo.m_Respawn = false;
@ -315,6 +320,8 @@ void CPlayer::SaveCharacter()
m_PauseInfo.m_LastWeapon = Character->m_LastWeapon; m_PauseInfo.m_LastWeapon = Character->m_LastWeapon;
m_PauseInfo.m_HammerType = Character->m_HammerType; m_PauseInfo.m_HammerType = Character->m_HammerType;
m_PauseInfo.m_Super = Character->m_Super; 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; CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;
m_PauseInfo.m_Team = Controller->m_Teams.m_Core.Team(GetCID()); m_PauseInfo.m_Team = Controller->m_Teams.m_Core.Team(GetCID());
m_PauseInfo.m_PauseTime = Server()->Tick(); m_PauseInfo.m_PauseTime = Server()->Tick();

View file

@ -57,6 +57,8 @@ public:
bool m_aHasWeapon[NUM_WEAPONS]; bool m_aHasWeapon[NUM_WEAPONS];
int m_HammerType; int m_HammerType;
bool m_Super; bool m_Super;
bool m_DeepFreeze;
bool m_EndlessHook;
int m_PauseTime; int m_PauseTime;
int m_Team; int m_Team;
} m_PauseInfo; } m_PauseInfo;

View file

@ -1,5 +1,7 @@
/* copyright (c) 2008 rajh and gregwar. Score stuff */ /* copyright (c) 2008 rajh and gregwar. Score stuff */
#include <base/tl/sorted_array.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>

View file

@ -25,4 +25,4 @@ public:
void Reset(); void Reset();
}; };
#endif #endif

View file

@ -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(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(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) 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)

View file

@ -2,6 +2,10 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/system.h> #include <base/system.h>
#include <engine/shared/network.h> #include <engine/shared/network.h>
#include <engine/shared/config.h>
#include <engine/console.h>
#include <engine/storage.h>
#include <engine/kernel.h>
#include "mastersrv.h" #include "mastersrv.h"
@ -10,6 +14,7 @@ enum {
MAX_SERVERS_PER_PACKET=128, MAX_SERVERS_PER_PACKET=128,
MAX_PACKETS=16, MAX_PACKETS=16,
MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS, MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS,
MAX_BANS=128,
EXPIRE_TIME = 90 EXPIRE_TIME = 90
}; };
@ -60,11 +65,23 @@ struct CCountPacketData
static CCountPacketData m_CountData; 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 int64 server_expire[MAX_SERVERS];
static CNetClient m_NetChecker; // NAT/FW checker static CNetClient m_NetChecker; // NAT/FW checker
static CNetClient m_NetOp; // main static CNetClient m_NetOp; // main
IConsole *m_pConsole;
void BuildPackets() void BuildPackets()
{ {
CServerEntry *pCurrent = &m_aServers[0]; 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; NETADDR BindAddr;
dbg_logger_stdout(); 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(data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); 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"); dbg_msg("mastersrv", "started");
@ -268,6 +348,9 @@ int main(int argc, char **argv) // ignore_convention
CNetChunk Packet; CNetChunk Packet;
while(m_NetOp.Recv(&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 && if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 &&
mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0) 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 // process m_aPackets
while(m_NetChecker.Recv(&Packet)) while(m_NetChecker.Recv(&Packet))
{ {
// check if the server is banned
if(CheckBan(Packet.m_Address)) continue;
if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) &&
mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) 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) if(time_get()-LastBuild > time_freq()*5)
{ {
LastBuild = time_get(); LastBuild = time_get();