Du startest den Code unter OnPlayerPickUpPickup, also wenn ein Spieler ein Pickup aufsammelt. Allerdings führst du den code mit der Schleife 500 mal aus.
Nimm:
for(new i = 0; i < MAX_PLAYERS; i++)
{
und unten
} raus.
Beiträge von |-|auke
-
-
Nun erstellen wir uns eine Funktion, mitder wir die Häuser auslesen und erstellen können:
LoadHouses ( )
{
new File:houses = fopen ( HOUSEFILE, io_read ) , content[ 512 ];
if ( !houses )
return 0;
new house; // Diese Variable wird bei jedem Durchlauf um 1 erhöht.
while ( fread ( houses , content ) ) // Jede Zeile = ein Schleifdurchlauf
{
// Parser © by me :P. Das erkläre ich nicht alles, denn das wäre 1. zu viel und 2. nicht das Thema.
new v[ 23 ][ 64 ] , bool:stop = false , s;
while ( stop != true )
{
if ( strfind ( content , "|" ) != -1 )
{
for ( new x; x < strfind ( content , "|" ); x++ )
v[ s ][ x ] = content[ x ];
strdel ( content , 0 , strfind ( content , "|" ) + 1 );
}
else
{
for ( new x; x < strlen ( content ); x++ )
v[ s ][ x ] = content[ x ];
stop = true;
}
if ( !strcmp ( v[ s ] , "NULL" , true ) )
format ( v[ s ] , 16 , "%d" , NULL );
if ( !strcmp ( v[ s ] , "YES" , true ) )
format ( v[ s ] , 16 , "%d" , YES );
if ( !strcmp ( v[ s ] , "NO" , true ) )
format ( v[ s ] , 16 , "%d" , NO );
s++;
} // Ab hier wird es erst interessant:
House[ house ][ sID ] = stv ( v[ 0 ] ); // ID aus Datei wird in sID gespeichert.
House[ house ][ InteriorID ] = AddInterior ( v[ 1 ] , stv ( v[ 2 ] ) , stv ( v[ 3 ] ) , stf ( v[ 4 ] ) , stf ( v[ 5 ] ) , stf ( v[ 6 ] ) , stf ( v[ 7 ] ) , stv ( v[ 8 ] ) , stv ( v[ 9 ] ) , stv ( v[ 10 ] ) , stv ( v[ 11 ] ) , v[ 12 ] , stv ( v[ 13 ] ) , stv ( v[ 14 ] ) , stf (v[ 15 ] ) , stf ( v[ 16 ] ) , stf ( v[ 17 ] ) , stf ( v[ 18 ] ) , stv ( v[ 19 ] ) , stv ( v[ 20 ] ) , stv ( v[ 21 ] ) , stv ( v[ 22 ] ) ); // Das Haus wird erstellt, und die interior id in InteriorID gespeichert
house++;
CreatedHouses++;
}
fclose ( houses );
return 1;
}Nun das selbe nochmal, aber diesmal für die andere Datei:
LoadHouseData ( )
{
new File:houses = fopen ( HOUSEDATAFILE , io_read ) , content[ 512 ];
if ( !houses )
return 0;
new house;
while ( fread ( houses , content ) )
{
// Parser © by me :P. Das erkläre ich nicht alles, denn das wäre 1. zu viel und 2. nicht das Thema.
new v[ 7 ][ 64 ] , bool:stop = false , s;
while ( stop != true )
{
if ( strfind ( content , "|" ) != -1 )
{
for ( new x; x < strfind ( content , "|" ); x++ )
v[ s ][ x ] = content[ x ];
strdel ( content , 0 , strfind ( content , "|" ) + 1 );
}
else
{
for ( new x; x < strlen ( content ); x++ )
v[ s ][ x ] = content[ x ];
stop = true;
}
s++;
}
HouseData[ house ][ sID ] = stv ( v[ 0 ] ); // Hier werden die HausData Werte beschrieben.
HouseData[ house ][ Prize ] = stv ( v[ 1 ] ); // Hier werden die HausData Werte beschrieben.
HouseData[ house ][ AllowRent ] = stv ( v[ 2 ] ); // Hier werden die HausData Werte beschrieben.
format ( HouseData[ house ][ Owner ] , 64 , v[ 3 ] ); // Hier werden die HausData Werte beschrieben.
format ( HouseData[ house ][ Tenant ] , 64 , v[ 4 ] ); // Hier werden die HausData Werte beschrieben.
HouseData[ house ][ Rent ] = stv ( v[ 5 ] ); // Hier werden die HausData Werte beschrieben.
HouseData[ house ][ Lockstate ] = stv ( v[ 6 ] ); // Hier werden die HausData Werte beschrieben.
house++;
}
fclose ( houses );
if ( CreatedHouses != house ) // Wenn die erzeugten Häuser mehr sind, als die Haus dazu Informationen ( id Verschiebung ect.. )
printf ( "The Housefiles may are incorrect. Please fix it to prevent Bugs!" );
return 1;
}Und nun noch eine kleine Funktion zum Speichern:
SaveHouseData ( )
{
new File:houses = fopen ( HOUSEDATAFILE , io_write ); // datei löschen
fclose ( houses );
houses = fopen ( HOUSEDATAFILE , io_append );
new Line[ 128 ];
if ( !houses )
return 0;
for ( new i; i < CreatedHouses + 1; i++ ) // Alle Häuser durchschleifen
{
format ( Line , 128 , "%d|%d|%d|%s|%s|%d|%d\r\n" , HouseData [ i ][ sID ] , HouseData[ i ][ Prize ] , HouseData[ i ][ AllowRent ] , HouseData[ i ][ Owner ] , HouseData[ i ][ Tenant ] , HouseData[ i ][ Rent ] , HouseData[ i ][ Lockstate ] ); // Neue Zeile zusammensetzen
fwrite ( houses , Line ); // Schreiben
}
fclose ( houses );
return 1;
}Damit wir gleich schnell und fröhlich mit den Befehlen ect. anfangen können, erstellen wir uns ein paar Funktionen, die uns das Leben leichter machen:
GetHouseIndex ( interior ) // Gibt den Index vom House Array, beidem InterioID das angegebende Interior ist
{
for ( new i; i < CreatedHouses + 1; i++ ) // Alle erzeugten Häuser durchschleifen
if ( House[ i ][ InteriorID ] == interior ) // Wenn InteriorID gleich interior ist, gieb den Index zurück
return i;
return -1;
}
GetHouseDataIndex ( interior ) // Gibt den Index vom HouseData Array. Gleiche funktionsweise wie oben
{
new saveID = House[ GetHouseIndex ( interior ) ][ sID ];
for ( new i; i < CreatedHouses + 1; i++ )
if ( HouseData[ i ][ sID ] == saveID )
return i;
return -1;
}
GetPlayerHouse ( playerid ) // Gibt den Index vom HouseData Array zurück, wenn dem Spieler ein Haus gehört.
{
new PlayerName[ MAX_PLAYER_NAME ];
GetPlayerName ( playerid , PlayerName , MAX_PLAYER_NAME );
for ( new i; i < CreatedHouses; i++ ) // Alle Häuser durchschleifen
if ( !strcmp ( HouseData[ i ][ Owner ] , PlayerName ) || !strcmp ( HouseData[ i ][ Tenant ] , PlayerName ) ) // Wenn der Spieler Mieter oder Besitzer ist, gib den index zurücl
return i;
return -1;
}Nun kommen wir zu dem spannenden Teil des Tutorials. Folgende 4 Callbacks müssen in´s Script kopiert werden:
public OnPlayerEnterInterior(playerid ,interior ,method)
{
return 1;
}public OnPlayerEnteredInterior(playerid ,interior ,method)
{
return 1;
}public OnPlayerLeaveInterior(playerid, interior, method)
{
return 1;
}public OnPlayerLeavedInterior(playerid, interior, method)
{
return 1;
}Damit die Variable ActualHouse auch einen Sinn hat, und nützlich wird, müssen wir sie beim Hineinkommen in ein Haus auf dessen InteriorID setzen. Beim verlassen wieder auf -1. Das geht mit den Callbacks OnPlayerEnteredIntrerior und OnPlayerLeavedInterior. Beide werden aufgerufen, wenn ein Spieler ein Haus betritt oder verlässt.
public OnPlayerEnteredInterior(playerid ,interior ,method)
{
ActualHouse[ playerid ] = interior;
return 1;
}
public OnPlayerLeavedInterior(playerid, interior, method)
{
ActualHouse[ playerid ] = -1;
return 1;
}
Nun kommen wir zu dem Teil, beidem der Spieler versucht ein Haus zu betreten. Dort müssen wir überprüfen ob...- ... das Haus eines von unseren erstellten ist
- ... es verschlossen ist
- ... der Spieler der Besitzer ist
- ... der Spieler der Mieter ist
- ... das Haus verkauft ist
- ... das Haus einen Mieter hat
- ... Ob das Haus zu vermieten ist
Das alles geschieht so:
public OnPlayerEnterInterior(playerid ,interior ,method) // Wenn der Spieler versucht ein Haus zu betreten
{
new HouseIndex = GetHouseIndex ( interior ) , HouseDataIndex = GetHouseDataIndex ( interior ) , PlayerName[ MAX_PLAYER_NAME ]; // Alle Variablen erstellen, und einige vordefinieren
GetPlayerName ( playerid , PlayerName , MAX_PLAYER_NAME );
if ( HouseIndex != -1 && HouseDataIndex != -1 ) // Wenn das Haus kein Haus aus diesem System ist
if ( HouseData[ HouseDataIndex ][ Lockstate ] == 0 ) // Prüfen ob das Haus abgeschlossen ist
{
if ( strcmp ( PlayerName , HouseData[ HouseDataIndex ][ Owner ] ) && strcmp ( PlayerName , HouseData[ HouseDataIndex ][ Tenant ] ) ) // Wenn die Person nicht Mieter oder Besitzer ist
{
new string[ 128 ];
if ( strcmp ( UNALLOWED_NAME , HouseData[ HouseDataIndex ][ Owner ] ) ) // Wenn das Haus verkauft ist
if ( !strcmp ( UNALLOWED_NAME , HouseData[ HouseDataIndex ][ Tenant ] ) ) // Wenn das Haus nicht vermietet ist
if ( HouseData[ HouseDataIndex ][ AllowRent ] == 0 ) // Wenn man nicht einmieten kann
format ( string , 128 , "Dieses Haus gehört %s." , HouseData[ HouseDataIndex ][ Owner ] );
else // Wenn man einmieten kann
format ( string , 128 , "Dieses Haus gehört %s. Hier kannst du für %d$ einmieten! Benutze \"renthouse\"" , HouseData[ HouseDataIndex ][ Owner ] , HouseData[ HouseDataIndex ][ Rent ] );
else // Wenn es vermietet und verkauft ist
format ( string , 128 , "Dieses Haus gehört %s. Mieter ist %s." , HouseData[ HouseDataIndex ][ Owner ] , HouseData[ HouseDataIndex ][ Tenant ] );
else // Wenn das Haus zu verkaufen ist
format ( string , 128 , "Dieses Haus ist für %d$ zu verkaufen. Zum Kaufen benutze \"/buyhouse\"" , HouseData[ HouseDataIndex ][ Prize ] );
SendClientMessage ( playerid , 0x666666AA , string );
}
}
else // Wenn das Haus abgeschlossen ist
{
SendClientMessage ( playerid , 0x666666AA , "Dieses Haus ist abgeschlossen!" );
return 0; // Spieler nicht hinein lassen
}
return 1;
}Nun müssen wir bei OnPlayerCommandText nur noch die Befehle für das Auf- und Abschließen, um das Haus zu kaufen, und um sich einzumieten erstellen.
Haus auf- und abschließen
if ( !strcmp ( cmdtext , "/lockhouse" ) )
{
new HouseDataIndex = GetPlayerHouse ( playerid );
if ( HouseDataIndex != -1 ) // Wenn der Index gültig ist
if ( HouseData[ HouseDataIndex ][ Lockstate ] == 0 ) // Wenn das Haus aufgeschlossen ist
{
HouseData[ HouseDataIndex ][ Lockstate ] = 1; // Türstatus auf "geschlossen"
SendClientMessage ( playerid , 0x666666AA , "Du hast das Haus abgeschlossen!" );
}
else // Wenn das Haus abgeschlossen ist
{
HouseData[ HouseDataIndex ][ Lockstate ] = 0; // Türstatus auf "offen"
SendClientMessage ( playerid , 0x666666AA , "Du hast das Haus aufgeschlossen!" );
}
else // Wenn der Index ungültig ist. -> Spieler besitzt kein Haus
SendClientMessage ( playerid , 0x666666AA , "Du besitzt kein Haus!" );
}
Haus kaufen
if ( !strcmp ( cmdtext , "/buyhouse" ) )
{
new HouseDataIndex = GetHouseDataIndex ( ActualHouse[ playerid ] ) , PlayerName[ MAX_PLAYER_NAME ] , string[ 128 ];
GetPlayerName ( playerid , PlayerName , MAX_PLAYER_NAME );
if ( ActualHouse[ playerid ] != -1 ) // Wenn sich der Spieler in einem Haus befindet
{
if ( GetPlayerHouse ( playerid ) != -1 ) // Wenn der Spieler ein eigenes Haus besitzt
return SendClientMessage ( playerid , 0x666666AA , "Du besitzt schon ein Haus!" );
if ( !strcmp ( HouseData[ HouseDataIndex ][ Owner ] , UNALLOWED_NAME ) ) // Wenn das Haus verkaufbar ist
{
if ( HouseData[ HouseDataIndex ][ Prize ] < _GetPlayerMoney ( playerid ) ) // Prüfen ob der Spieler genug Geld besitzt
{
_GivePlayerMoney ( playerid , 0 - HouseData[ HouseDataIndex ][ Prize ] ); // Wert negativieren, und Geld abziehen
format ( HouseData[ HouseDataIndex ][ Owner ] , MAX_PLAYER_NAME , PlayerName ); // Neuen Besitzer eintragen
format ( string , 128 , "Du hast die dieses Haus für %d$ gekauft!" , HouseData[ HouseDataIndex ][ Prize ] );
}
else // Wenn der Spieler nicht genug Geld besitzt
format ( string , 128 , "Du hast nicht genug Geld für dieses Haus. Du benötigst %d$!" , HouseData[ HouseDataIndex ][ Prize ] );
return SendClientMessage ( playerid , 0x666666AA , string );
}
else // Wenn das Haus nicht zu verkaufen ist
return SendClientMessage ( playerid , 0x666666AA , "Dieses Haus ist nicht zu verkaufen!" );
}
else // Wenn sich der Spieler in keinem Haus befindet
return SendClientMessage ( playerid , 0x666666AA , "Du befindest dich in keinem Haus!" );
}
Haus mieten
if ( !strcmp ( cmdtext , "/renthouse" ) )
{
new HouseDataIndex = GetHouseDataIndex ( ActualHouse[ playerid ] ) , PlayerName[ MAX_PLAYER_NAME ] , string[ 128 ];
GetPlayerName ( playerid , PlayerName , MAX_PLAYER_NAME );
if ( ActualHouse[ playerid ] != -1 )
{
if ( GetPlayerHouse ( playerid ) != -1 ) // Wenn der Spieler ein Haus besitzt
return SendClientMessage ( playerid , 0x666666AA , "Du wohnst schon in einem Haus!" );
if ( !strcmp ( HouseData[ HouseDataIndex ][ Tenant ] , UNALLOWED_NAME ) && HouseData[ HouseDataIndex ][ AllowRent ] && strcmp ( HouseData[ HouseDataIndex ][ Owner ] , PlayerName ) ) // Wenn das Haus einen Besitzer hat, und keinen Mieter hat
{
format ( HouseData[ HouseDataIndex ][ Tenant ] , MAX_PLAYER_NAME , PlayerName ); // Spielername als neuen Mieter eintragen
format ( string , 128 , "Du bist nun Untermieter dieses Haus für %d$!" , HouseData[ HouseDataIndex ][ Rent ] );
}
else // Wenn das Haus nicht verkauft, oder schon vermietet ist
return SendClientMessage ( playerid , 0x666666AA , "Du kannst hier nicht einmieten." );
}
else // Wenn sich der Spieler in keinem Haus befindet
return SendClientMessage ( playerid , 0x666666AA , "Du befindest dich in keinem Haus!" );
}
Nun haben wir so einfach und schnell schon alle nützlichen Befehle erstellt! Weitere Befehle wie /unrenthouse oder /sellhouse können so ganz leicht nachgemacht werden.Damit das ganze System auch lädt und speichert, müssen wir nun nur noch unter OnGameModeInit laden und unter OnGameModeExit speichern lassen.
public OnGameModeInit()
{
LoadHouses ( );
LoadHouseData ( );
return 1;
}public OnGameModeExit()
{
SaveHouseData ( );
return 1;
}Nun fehlt allerdings noch der Punkt, andem der Spieler die Miete bezahlen muss.
Ich habe nun keinen Payday oder sonstiges gecodet, weil es nicht zum Tutorial dazu gehört.
Allerdings habe ich schon eine Funktion angefangen, mitder ein Payday oder derartiges einfach möglich ist zu erstellen.
stock HandleAllRents ( )
{
for ( new i; i < CreatedHouses + 1; i++ )
{
if ( HouseData[ GetHouseDataIndex ( i ) ][ RentAllowed ] && strcmp ( HouseData[ GetHouseDataIndex ( i ) ][ Tenant ] , UNALLOWED_NAME ) )
{
new Houseowner = GetPlayeridByName ( HouseData[ GetHouseDataIndex ( i ) ][ Owner ] ); // Hausbesitzer
new Tenant = GetPlayeridByName ( HouseData[ GetHouseDataIndex ( i ) ][ Tenant ] ); // Hausmieter
}
}
}
Diese Funktion benötigt noch eine weitere sehr simple Funktion, die ich nicht weiter erklären werde:
stock GetPlayeridByName ( name[ ] )
{
new TempName[ MAX_PLAYER_NAME ];
for ( new i; i < MAX_PLAYERS; i++ )
{
GetPlayerName ( i , TempName , MAX_PLAYER_NAME );
if ( strcmp ( TempName , name ) )
return i;
}
}Das gesamte Ergebniss als Gamemode könnte das in etwa so aussehen: http://pastebin.com/8s7tut1r
Ich hoffe ich habe euch geholfen.
Feedback erwünscht. -
Hallo Leute,
ich habe beschlossen ein Tutorial über das erstellen eines Haussystems zu machen.
Dies ist kein Scripting-Basics Tutorial, und verlang mindestens Grundwissen und ein funktionierendes Gehirn um es zu verstehen!
Fangen wir mal an...Das Ziel:
Das Ziel dieses Tutorials ist es, am Ende ein Haussystem zu haben, das Häuser automatisch beim Spielstart erstellt. Spieler sollen die Häuser kaufen, vermieten und abschliessen können. Dabei soll das System möglichst wenig Arbeitsaufwand haben. Natürlich soll das Script nur so wenig Ressourcen brauchen, wie es machbar ist.Der Weg:
Um unser Ziel zu verwirklichen werden wir 2 Dateien erstellen. In der einen Datei werden die Häuser zeilenweise gespeichert. In der anderen Datei werden wir das "Setup" des Hauses speichern. Also alle Informationen, wie z.B. Besitzer, Mieter, Miete ect..
Um das ganze möglichst komfortabel zu gestalten verwenden wir das Filterscript h_interiors. Dies erweitert die SA:MP um 6 neue Callbacks und Funktionen.Die Dateien:
.HOUSES - Datei
Die Datei für die Häuser wird in etwa das Layout wie die AddInteriors() Funktion in h_interiors bekommen. Jedoch mit einem "|" als Zwischenzeichen, und einer ID am Anfang. Die ID dient der Zuordnung, damit wir die Hauskonfiguration aus der 2. Datei auch einem Haus zuordnen können.
So würde eine solche Datei dann aussehen:Code1|Welcome home|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES 2|Welcome Home|NULL|0|1959.484252|1340.293334|15.374607|1.088764|NULL|NULL|NULL|YES|Bye|NULL|2|225.111801|1240.140380|1082.140625|96.546875|NULL|NULL|NULL|YES
Die ID am Anfang ist fortlaufend. (So wie man es z.B. von MySQL her kennt.
.HOUSEDATA - Datei
Die Housedata Datei ist eine viel kleinere Datei. In ihr wird nach folgendem Layout gespeichert:
Somit könnte eine solche Datei so aussehen:Diese 2 Datein legen wir nun mit Hilfe von der Windows Konsole an. Benutzer anderer Systeme werden schon wissen, wie sie das am einfachstem machen...
Wir öffnen die Windows Konsole.
Windows XP Benutzer:
Start -> Ausführen -> cmd eingeben -> Enter drücken
Windows Vista & 7 Benutzer:
Start -> cmd eingeben -> Enter drücken
Nun gebt ihr folgende Zeilen ein:
Danach können wir die Konsole schließen, und die 2 neuen Dateien auf dem Desktop in den Ordner Scriptfiles kopieren.Häuser erstellen:
Am besten erstellen wir die Häuser mit dem AddInteriors Generator von h_interiors. Die Beschreibung und Bedienung mit einem Video sind hier zu finden. Wir müssen nun lediglich den generierten Funktionsaufruf ( AddInterior(....) ) umschreiben. Das machen wir, indem wir alles außer der Parameter entfernen, und zwischen die Parameter ein "|" einfügen.
Also wird aus:CodeAddInterior ( "Welcome home!" , NULL , 0 , 1953.704956 , 1342.881958 , 15.374607 , 86.697219 , NULL , NULL , NULL , YES , "byee" , NULL , 3 , 235.407196 , 1187.490844 , 1080.257812 , 83.480270 , NULL , NULL , NULL , YES );
das:CodeWelcome home!|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES
Zum Schluss fügen wir vorne noch die ID ein. Dann wird daraus das:Code1|Welcome home!|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES
In der HOUSES Datei sähe das mit mehreren Häusern so aus:Code1|Welcome home!|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES 2|Welcome home!|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES 3|Welcome home!|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES 4|Welcome home in your Villa|NULL|0|1953.704956|1342.881958|15.374607|86.697219|NULL|NULL|NULL|YES|byee|NULL|3|235.407196|1187.490844|1080.257812|83.480270|NULL|NULL|NULL|YES
--- Optional!
Um mit dem AddInterior Generator direkt dieses Layout zu erstellen, muss in h_interiors mit AddInterior Generator die Zeile 543 mit dieser:
format ( function , 1024 , "%s|%s|%d|%f|%f|%f|%f|NULL|NULL|NULL|%s" , p[ playerid ][ iM ] , VWorld , p[ playerid ][ iIID ] , p[ playerid ][ iX ] , p[ playerid ][ iY ] , p[ playerid ][ iZ ] , p[ playerid ][ iA ] , AK );
und die Zeile 553 mit dieser Zeile ersetzt werden!
format ( temp_function , 512 , "|%s|%s|%d|%f|%f|%f|%f|NULL|NULL|NULL|%s" , p[ playerid ][ oM ] , VWorld , p[ playerid ][ oIID ] , p[ playerid ][ oX ] , p[ playerid ][ oY ] , p[ playerid ][ oZ ] , p[ playerid ][ oA ] , AK );
---Das Scripting (endlich):
Als erstes empfieht es sich die h_interiors include und ein paar defines und kleine Makros einzufügen:
#include <h_interiors> // h_interiors include einbinden
#define MAX_HOUSES 10 // Anzahl maximaler Häuser
#define HOUSEFILE "tutorial.HOUSES" // Datei aller Häuser
#define HOUSEDATAFILE "tutorial.HOUSEDATA" // Datei der Hausinformationen
#define stf(%0) floatstr(%0) // Kürzeres floatstr
#define stv(%0) strval(%0) // Kürzeres strval
#define UNALLOWED_NAME "-1NOBODY-1" // Ein Spielername dient als Platzhalter.
#define _GetPlayerMoney(%0) GetPlayerMoney(%0) // Kann geändert werden ( bei z.B. Anticheat System )
#define _GivePlayerMoney(%0,%1) GivePlayerMoney(%0,%1) // Kann geändert werden ( bei z.B. Anticheat System )Nun legen wir ein paar Variablen an, die wir benötigen werden:
enum houseinfo // Mehr muss von den Häusern nicht gespeichert werden, dank h_interiors.
{
sID, // sID wird die ID aus den Datein
InteriorID // InteriorID ist die ID, die von AddInterior zurückgegeben wird.
}enum housedata // Hier befinden sich die ganzen Hausinformationen
{
sID, // sID wird die ID aus den Datein
Prize, // Haus Kaufpreis
AllowRent, // Mieten erlauben 0 = Nein , 1 = Ja
Owner[ MAX_PLAYER_NAME ], // Besitzername
Tenant[ MAX_PLAYER_NAME ],// Mietername
Rent, // Mietkosten
Lockstate // Türschloss 0 = Offen , 1 = Verschlossen
}new HouseData[ MAX_HOUSES ][ housedata ];
new House[ MAX_HOUSES ][ houseinfo ];
new ActualHouse[ MAX_PLAYERS ];// Interior, indem sich der Spieler befindet
new CreatedHouses; // Anzahl erzeugter HäuserNun sollten wir als erstes prüfen, ob ein Spieler mit unerlaubtem Namen verdinden möchte. Das geschieht so:
public OnPlayerConnect(playerid)
{
new name[ MAX_PLAYER_NAME ];
GetPlayerName ( playerid , name , MAX_PLAYER_NAME );
if ( !strcmp ( name , UNALLOWED_NAME ) )
{
SendClientMessage ( playerid , 0x666666AA , "Es tut uns leid, aber dieser Name ist nicht zulässig." );
Kick ( playerid );
}
return 1;
}Darauf gehe ich nicht detailierter ein, denn das sollte wohl klar sein.Ich musste das Tutorial leider in 2 Teile teilen...
also wartet auf Teil 2 -
ocmd:money100(playerid,params[])
{
for ( new i; i != MAX_PLAYERS; i++ )
GivePlayerMoney(i,100000);
SendClientMessageToAll(playerid,0x33AA33AA,"Du hast dir 50K gegeben!");
return 1;
} -
Unabhängig vom Empfang hast du als Client (je nach Anzahl der Mitspieler) 2-5kb/s Datenvolumen.
Wenn dem so wäre, könnte er auch mit Tempodrosselung spielen. Demnach würde das Überschreiten des Volumens keine Auswirkung haben.
Allerdings würde dein Ping immer recht hoch sein. Ich schätze mal so 150 - 400ms. -
new OnlinePlayers;
public OnPlayerSpawn ( playerid )
{
if ( !IsPlayerNPC ( 0 ) )
{
OnlinePlayers++;
new File:rekord = fopen ( "rekord.txt" , io_read ) , cnt[ 6 ];
fread ( rekord , cnt );
if ( strval ( cnt ) < OnlinePlayers )
{
new ncnt[ 6 ] , msg[ 64 ];
fclose ( rekord );
rekord = fopen ( "rekord.txt" , io_write );
format ( ncnt , 6 , "%d" , OnlinePlayers );
fwrite ( rekord , ncnt );
format ( msg , 64 , "Der aktuelle Rekord von %d Spielern wurde gebrochen. ( Aktuell %d Spieler online )" , strval ( cnt ) , strval ( ncnt ) );
SendClientMessageToAll ( 0x666666AA , msg );
}
fclose ( rekord );
}
}public OnPlayerDisconnect(playerid, reason)
{
OnlinePlayers--;
} -
Ja von 0 an. Wenn du keine 0 möchtest, kannst du das so machen:
new value;
while ( value == 0 )
value = random(3)+18975; -
hey wenn ich bei meinem Script Spawn und dann sage
#define vagosspawn -2183.0176,957.6070,80.0000
kann ich dan noch sagen das er wenn er spawnt ein skin bekommen soll???
Also So
#define vagosspawn 180,-2183.0176,957.6070,80.0000
jup, über einen kleinen Umweg:
#define vagosspawn 180,-2183.0176,957.6070,80.0000
SetSpawn ( playerid , skin , Float:X , Float:Y , Float:Z )
{
SetPlayerPos ( playerid , X , Y , Z );
SetPlayerSkin ( playerid , skin );
}public OnPlayerSpawn ( playerid )
{
SetSpawn ( playerid , vagosspawn );
} -
Danke fürs feedback!
@musel: Nein, es gibt nun keine kostenpflichtige Version mehr. Und ich denke es wird auch keine kostenpflichtige mehr geben.
-
@ AppLe96: Danke
@ noir: Ich hatte es schon kurz mal versucht, es gelang mir allerdings nicht. Und danach hatte ich es leider vergessen, sry.. Ich werd es nochmal richtig versuchen. -
Toxic_Tomato: Mach ich vielleicht mal, wenn ich Zeit hab. Vielleicht hat´s bis dahin ja schon jemand anderes gemacht...
@Razor1225: Danke -
An OOP sollte man bei diesem Grundwissen allerdings auch noch nicht denken.
-
Ich mache ja eigentlich keine Werbung für meine scripts, in help topics aber das ist genau das Einsatzgebiet von meinem Filterscript + Include: [ FILTERSCRIPT ] H_Interiors 1.1 - Perfekt für eigenes Haussystem!
-
-
Danke euch vieren!
Edit: Statt beiden, vieren ..
-
-
$aDoor ist also ein einziffriger Integer.
Wozu ist dann die Schleife gut?
Was passiert, wenn du $aDoor einfach mal am Anfang ausgibst? - Hat sie einen Inhalt? -
ocmd:setzeitung(playerid, params[])
{
if(!isPlayerAnAdmin(playerid,2))
{
SendClientMessage (playerid,GRAU,"Du darfst diesen Befehl nicht benutzen!");
}
new pIN[128];
if(sscanf(params,"s",pIN))
{
SendClientMessage(playerid,GRAU,"Benutze: /setzeitung [Inhalt]");
}
format(zeitungdatei,sizeof(zeitungdatei),"/ACCS/zeitung.ini");
dini_Create(zeitungdatei);
dini_Set(zeitungdatei,"Wetter",pIN);
return 1;
}Ich kenne dini nicht aus dem Kopf. Aber irgendwie so sollte es gehen.
-
Wenn ich mir das so anschaue, sieht es aus, als möchtest du einen string speichern.
dann mit pIN ein Array werden, und dann wird auch die Funktion dini_Int falsch sein. -
Zeig die Zeile in der new score[..] steht.