Sie sind nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: sourceserver.info. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

1

Freitag, 8. Juli 2011, 22:36

Mathmos Frageecke zu Sourcepawn

Um Threadspam zu vermeiden, dachte ich mir, machst du ein Thema, wo ich alle meine Fragen und Probleme posten kann ;)

So, nun mal zu meiner ersten Frage.

Ich möchte aus einer Cvar den Wert auslesen, dafür gibt’s ja "GetConVar..."
Nun bin ich eben auf der Suche nach dem obigen Befehl auf "FindConVar" gestoßen.
Jetzt würde ich gerne wissen, was es damit auf sich hat. In einigen Plugins verstehe ich das so, dass sie einfach als Abfrage, ob diese Cvar vorhanden ist, genutzt wird.
Wenn ich das richtig verstanden habe, wieso sollte man die Existenz dieser Cvar überprüfen?

fluxX

Super Moderator

Beiträge: 1 056

Wohnort: Österreich

Beruf: IT Systemadministrator

Rootserver vorhanden: Ja

  • Nachricht senden

2

Freitag, 8. Juli 2011, 23:34

mit FindConVar bekommst du ein Handle zu einem bereits existierenden convar
zb. mp_freezetime usw

3

Freitag, 8. Juli 2011, 23:55

Ok, aber was genau ist eigentlich ein Handle.
Ich sehe das zwar immer und überall, aber so richtig was anfangen kann ich damit noch nicht ;)

Nun aber mal zu einem Problem, an dem ich nun schon einige Zeit dokter aber nichts vernünftiges bei rum komm.
Ich versuche einen Timer zu erstellen und mit diesem dann eine Funktion aus zu rufen, an die dann zwei Variablen übergeben werden sollen...
Mittlerweile habe ich schon einiges probiert, aber leider gab es immer eine Fehlermeldung.

Hier der Timer wie er aktuell aussieht.

Quellcode

1
CreateTimer(restart_delay, Balance, (teamT, teamCT));


Hier die Funktion wie sie aktuell aussieht.

Quellcode

1
public Action:Balance(Handle:timer, any:teamT, any:teamCT)

fluxX

Super Moderator

Beiträge: 1 056

Wohnort: Österreich

Beruf: IT Systemadministrator

Rootserver vorhanden: Ja

  • Nachricht senden

4

Samstag, 9. Juli 2011, 00:38

in pawn hat jedes handle einen typ. zB cvar handle, timer handle, datenbank handle usw...
Das handle macht ansich nichts, das ist nur ein zeiger auf irgendwas und dann gibt es funktionen denen du dieses handle mitgeben musst, damit die wissen auf was sie ihre funktion machen sollen.
wenn zB das handle geschlossen wird, also der speicher auf den es zeigt überschrieben wird, dann gibt es diese invalid handle errors wie zB bei KillTimer, da das handle halt auf keinen timer mehr zeigt.
und du musst fast alle handles selbst mit CloseHandle() schließen, sonst bleibt der speicher die ganze zeit reserviert und irgendwann ist der halt voll und der server freezed oder so.. wäre nicht so toll ^^
also immer genau auf deine handles aufpassen!

convar handles musst du nicht selbst schließen, das übernimmt sourcemod, wie zb. g_cVarTest = CreateConVar ("sm_test_......);
wenn das plugin unloaded wird, dann werden auch alle offenen handles geschlossen


bei deinem CreateTimer fehlt der Timer.. Zeit ist immer in sekunden.. Zeit kannst halt selber wählen.. vergiss nicht das .0
Versuch mal

Quellcode

1
CreateTimer(30.0, restart_delay, Balance, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);


poste mir mal die fehler meldung ^^

5

Samstag, 9. Juli 2011, 07:34

Egal, ob nach deinem oder nach meinem oder noch anderem Code, kommt der selbe Fehler.



Aber bei mir hat die Zeitangabe nicht gefehlt.
Die Variable "restart_delay" ist meine Zeitangabe ;)

In Beispielen habe ich gesehen, das man TIMER_REAPEAT u.ä. weglassen kann, wenn man nicht vor hat diesen zu wiederholen.
Aber bei deinem Timer werden nicht meine beiden Variablen (teamT, teamCT) an meine Funkion "Balance" übergeben, oder doch?

6

Mittwoch, 13. Juli 2011, 16:25

Wiedermal habe ich eine Frage.

Ich möchte in der while Abfrage noch abfragen, ob derjenige schon im Array drin steht.
Dabei darf allerdings nicht das erste Feld abgefragt werden, da ich dort keinen Client drin Speicher.

Quellcode

1
2
3
4
5
6
7
8
9
for (new i=1; i<g_diff; i++)
{
	do
	{
		client = GetRandomInt(1, MaxClients);
		g_players[i] = client;
	}
	while(!IsClientInGame(client) || GetClientTeam(client) != TS);
}


Gibts es zudem ne Möglichekit ein Array dynamisch zu gestalten?
Was ich möchte, ist ein globales Array, dem ich aber erst jede Runde die größe sage.
Ist dies möglich?

7

Montag, 18. Juli 2011, 11:58

Soweit hab ich jetzt alles auf die Reihe bekommen...
Und klappt jetzt auch alles wunderbar, sogar ohne Error Log ^^

Nun möchte ich noch eine Adminabfrage Einbauen.
Hab mich auch schon in einigen andern Plugins umgesehen, aber leider nichts Brauchbares gefunden...

Evt hat ja jemand, speziell fluxX, ein kleines Beispiel ;)

Das was ich bisher probiert habe funzt so rein gar nicht.

Aktueller Stand:
Dabei springen auch 2 Warnings raus

Quellcode

1
2
3
4
5
6
7
8
9
new AdminId:adminid;
for (new i = 1; i <= MaxClients; i++)
{
  adminid = GetUserAdmin(i);
  if ((IsClientInGame(i) && (GetClientTeam(i) == TS)) && !(GetAdminFlag(adminid, Admin_Kick)))
  {
    PushArrayCell(g_adtClientlist, i);
  }
}

fluxX

Super Moderator

Beiträge: 1 056

Wohnort: Österreich

Beruf: IT Systemadministrator

Rootserver vorhanden: Ja

  • Nachricht senden

8

Montag, 18. Juli 2011, 15:42

Adminabfrage für was?
mehr infos würden schon gut tun.. hab grad kein plan was du willst xD ^^

9

Montag, 18. Juli 2011, 16:34

Naja, es sollen halt nur Leute in das Array geschrieben werden, die kein Admin sind.

Hab jetzt was anderes gefunden, was auch funktioniert, solange die Schleife nur einmal durch läuft.
Sobald sie öfter durch läuft bekomm ich n Fehler.


Quellcode

1
2
3
4
5
6
7
for (new i = 1; i <= MaxClients; i++)
{
     if (IsClientInGame(i) && IsClientConnected(i) && (GetClientTeam(i) == TS) && (GetUserAdmin(i) == INVALID_ADMIN_ID))
     {
          PushArrayCell(g_adtClientlist, i);
     }
}


Aber hab dich mal in Steam geaddet ;)

Kathy

Fortgeschrittener

Beiträge: 523

Wohnort: München

Beruf: Roaster/Freelance Editor

Rootserver vorhanden: Ja

  • Nachricht senden

10

Mittwoch, 20. Juli 2011, 18:26

Offtopic: Ich habe deine Frage ecke mal in die "Eigene Scripts" ecke verschoben.


NTcgNjggNmYgNjEgMmUgMjAgNDQgNjUgNmEgNjEgMjAgNzYgNzUgMmU=

Wer weiss was das ist?

11

Mittwoch, 20. Juli 2011, 21:26

Habs nun hinbekommen mit der Adminabfrage.

Nun aber wieder ein neues Problem^^

Ich bekomme immer die schöne Fehlermeldung "tag mismatch"

Hier mal der betroffene Codeschnipsel:

PHP-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
new Handle:g_cvar_checkinterval;
new Handle:g_roundend_counter;

public OnPluginStart()
{
    g_cvar_checkinterval CreateConVar("sm_checkinterval""1.0""team balance after x rounds"0true1.0);

    HookEvent("round_end"Event_RoundEnd)
    g_Cvar_round_restart_delay FindConVar("mp_round_restart_delay");
}

public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
    new Float:restart_delay GetConVarFloat(g_Cvar_round_restart_delay);    
    g_roundend_counter++;
    if (g_cvar_checkinterval == g_roundend_counter)
    {
        CreateTimer((restart_delay-0.1), Balance);
        g_roundend_counter 0; (<---- tag mismatch Zeile)
    }

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Mathmos« (20. Juli 2011, 21:42)


12

Donnerstag, 28. Juli 2011, 08:50

Kathy hat in einem andern Thread folgende Codezeile verwendet.

PHP-Quelltext

1
if( ( ( inGameOnly ) ? IsClientInGame) : IsClientConnected) ) && !IsFakeClient) )

Nun würde ich mal gerne wissen, was das mit dem Fragezeichen und dem Doppelpunkt auf sich hat.
&& und || ist mir bekannt, aber die andern beiden Operatoren leider nicht.
Habs mittlerweile schon des Öfteren gesehen, aber leider konnte ich mir da keinen Reim drauf bilden.

HSFighter

Administrator

Beiträge: 1 517

Wohnort: Flensburg

Beruf: Industrieelektroniker

Rootserver vorhanden: Nein

  • Nachricht senden

13

Donnerstag, 28. Juli 2011, 13:00

Kathy hat in einem andern Thread folgende Codezeile verwendet.

PHP-Quelltext

1
if( ( ( inGameOnly ) ? IsClientInGame) : IsClientConnected) ) && !IsFakeClient) )

Nun würde ich mal gerne wissen, was das mit dem Fragezeichen und dem Doppelpunkt auf sich hat.
&& und || ist mir bekannt, aber die andern beiden Operatoren leider nicht.
Habs mittlerweile schon des Öfteren gesehen, aber leider konnte ich mir da keinen Reim drauf bilden.


Das ist die abgekürzte Schreibweise für IF-THEN-ELSE-Konstruktionen.

"?" = "Then" = "{"
":" = "Else" = "} Else {"

PHP-Quelltext

1
(count ($links) > 1) ? ($links join (" | ",$links)) : ($links "");

PHP-Quelltext

1
2
3
4
5
6
if (count ($links) > 1)
{
$links join (" | ",$links);
} else {
$links "";
}



-
Anti Cheat: www.smacbans.com
Kein direkter Support per PM (nur auf Anforderung)

14

Donnerstag, 28. Juli 2011, 13:23

Ah, alles klar. Danke =)

15

Sonntag, 25. Dezember 2011, 18:20

Ich bin gerade dabei ein Menu zu erstellen.
Allerdings finde ich es tierisch aufwändig, wenn man mehrere Menüs bzw Sub-Menüs hat.
Das ist jetzt gerade mal ein Menü und ein Sub-Menü und das ist schon recht viel Code.
Geht das nicht irgendwie kürzer?

Spoiler Spoiler

PHP-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <sourcemod>
#include <cstrike>

public OnPluginStart()
{
    RegConsoleCmd("panel_test1"Panel_Test1);
}
 
public PanelHandler1(Handle:menuMenuAction:actionparam1param2)
{
    if (action == MenuAction_Select)
    {
        PrintToConsole(param1"You selected item: %d"param2);
        if (param2 == 1)
        {
            Panel_Test2(param10);
        }
    }
    else if (action == MenuAction_Cancel)
    {
        PrintToServer("Client %d's menu was cancelled.  Reason: %d"param1param2);
    }
}
 
public PanelHandler2(Handle:menuMenuAction:actionparam1param2)
{
    if (action == MenuAction_Select)
    {
        PrintToConsole(param1"You selected item: %d"param2);
        if (param2 == 1)
        {
            Panel_Test1(param10);
        }
    }
    else if (action == MenuAction_Cancel)
    {
        PrintToServer("Client %d's menu was cancelled.  Reason: %d"param1param2);
    }
}

public Action:Panel_Test1(clientargs)
{
    new Handle:panel CreatePanel();
    DrawPanelItem(panel"BLUB1");
    DrawPanelItem(panel"BLUB1");
    DrawPanelItem(panel"BLUB1");
    DrawPanelItem(panel"BLUB1");
    DrawPanelText(panel"BLUB1");
 
    SendPanelToClient(panelclientPanelHandler120);
 
    CloseHandle(panel);
 
    return Plugin_Handled;
}

public Action:Panel_Test2(clientargs)
{
    new Handle:panel CreatePanel();
    DrawPanelItem(panel"BLUB2");
    DrawPanelItem(panel"BLUB2");
    DrawPanelItem(panel"BLUB2");
    DrawPanelItem(panel"BLUB2");
    DrawPanelText(panel"BLUB2");
 
    SendPanelToClient(panelclientPanelHandler220);
 
    CloseHandle(panel);
 
    return Plugin_Handled;
}

16

Sonntag, 25. Dezember 2011, 23:54

AFAIK: Nein =(
Verändere die Sourcewelt so wie du es willst ;)
(Durch modifizieren, spawnen, laden, speichern von Entities)
Extended Grabbermod -> Ent-Control

17

Montag, 26. Dezember 2011, 16:12

schade aber auch...

Nun bin ich gerade dabei mich mit SQL zu beschäftigen. Allerdings verstehe ich nur Bahnhof....
Den Code habe ich mir von folgendem Plugin besorgt: http://forums.alliedmods.net/showthread.php?p=582823
Funktioniert auch und erstellt eine Tabelle.
Aber verstehen tu ich nichts. Kennt sich da jemand mit näher aus und kann mir das ein bisschen näher bringen?
Aus dem SM Wiki Eintrag werde ich auch nicht schlauer.

Spoiler Spoiler

PHP-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
new Handle:g_hDatabase INVALID_HANDLE;

public OnPluginStart()
{
    SQL_TConnect(sql_Connect"db_mysql");
}

public sql_Connect(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (hndl == INVALID_HANDLE)
    {
        SetFailState("Database failure: %s"error);
    }
    else
    {
        g_hDatabase hndl;
    }

    CreateTables();
    SendQuery("SET NAMES 'utf8'");
}

public sql_Query(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (hndl == INVALID_HANDLE)
    {
        ResetPack(data);

        decl String:query[512];
        ReadPackString(dataquerysizeof(query));

        LogError("Query Failed! %s"error);
        LogError("Query: %s"query);
    }
    CloseHandle(data);
}
 
 SendQuery(String:query[])
{
    new Handle:dp CreateDataPack();
    WritePackString(dpquery);
    SQL_TQuery(g_hDatabasesql_Queryquerydp);
}

CreateTables()
{
    static String:sQuery[] = "\
        CREATE TABLE IF NOT EXISTS `db_1`( \
          `id` int(11) NOT NULL AUTO_INCREMENT, \
          `name` varchar(65) NOT NULL, \
          `steamid` varchar(32) NOT NULL, \
          `map` varchar(32) NOT NULL, \
          `serverip` varchar(16) NOT NULL, \
          `serverport` varchar(6) NOT NULL, \
          `game` varchar(32) NOT NULL, \
          `feedback` varchar(255) NOT NULL, \
          `date` timestamp NOT NULL default CURRENT_TIMESTAMP, \
          PRIMARY KEY (`id`) \
        ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;";

    SendQuery(sQuery);
}

18

Montag, 26. Dezember 2011, 22:53

So langsam habe ich das wohl doch verstanden, wobei da python echt einfach ist.
Aber wenn mir das doch noch jemand erklären will habe ich nichts dagegen =)

Nun habe ich vor, da das Menü und der SQL Kram doch einige Zeilen in Anspruch nehmen, das ganze auszulagern.
Soll heißen, ich schreibe das Menü und den SQL Kram in eine extra Datei und include sie dann in meine main.sp.

Nun aber zu meine Problem.
ZB. brauche ich die Funktion "public OnPluginStart()" in meiner main.sp aber auch in der sql.inc (ich habe es einfach mal so genannt, ist ja glaube ich egal ob sp oder inc oder blub, oder?).
Wenn ich das nun compiliere bekomme ich eine Fehlermeldung, dass OnPluginStart schon definiert ist.
Wie kann ich das nun umgehen? Bzw, wie muss man es schreiben, damit ich Funktionen in mehrern Dateien benutzen kann?

Edit: Mir ist gerade die Idee gekommen, dass ich die Funktion OnPluginStart in der sql.in umbenennen kann, zB in SQL_OnPluginStart und dies dann von der originalen OnPluginStart Funktion, die sich ja in der main.sp befindet, aufrufen lasse. Ist zwar nicht die optimalste Lösugn, aber würde ja funktionieren.
btw, wann muss ich eignetlich vor ne Funktion "public" schreiben und wann nicht?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Mathmos« (26. Dezember 2011, 23:02)


Impact

Super Moderator

Beiträge: 1 276

Rootserver vorhanden: Nein

  • Nachricht senden

19

Montag, 26. Dezember 2011, 23:36

Viele Fragen auf einmal :)
  • public: A callback function that is visible to the application and other scripts.

Sprich Callbacks, Events, Vordefinierte Forwards, diese brauchen ein Public.
Steht aber auch alles in der Introduction...

Ich musste diese Technik bisher noch nicht anwenden, aber wenn du danach arbeitest hast du normalerweise immer eine main.sp, diese ist meist sehr klein da darin kein wirklicher Code steht.
In dieser deklarierst du alles was du brauchst, Hooks, Callbacks, Events, etc.
In der jeweiligen Datei hast du dann du dann deinen Callback der durch die main.sp erstellt wurde.
Im Prinzip kommt dabei das gleiche Raus, allerdings kannst du das machen wie es dir lieb ist, performancemäßig sollte es keine besonders großen Auswirkungen haben, ansonsten kannst du ja mit dem Profiler selbst testen.

Ich hab dir im Anhang ein kleines Beispiel geschrieben.

MfG
Impact
»Impact« hat folgende Dateien angehängt:
  • main.sp (398 Byte - 140 mal heruntergeladen - zuletzt: 29. März 2024, 03:20)
  • events.sp (214 Byte - 130 mal heruntergeladen - zuletzt: 25. August 2023, 10:16)
  • commands.sp (198 Byte - 144 mal heruntergeladen - zuletzt: 29. März 2024, 03:09)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Impact« (26. Dezember 2011, 23:49)


20

Dienstag, 27. Dezember 2011, 00:17

Jap, es muss sich ja auch lohnen ;)

Erstmal danke, aber kannst du das auch noch so formulieren, dass ein "nicht programmierer" es versteht?
Ich verstehe die ganzen Begriffe wie, Callbacks, Forwards,....., nicht.
Aber der Link hilft mir bestimmt bei dem ein oder andern Dingen weiter.

Bei deinem Beispiel hast du ein paar Sachen drin, wo ich auch gleich mal nachfragen muss =)

#pragma semicolon 1 : Das habe ich schon bei einigen Addons gesehen, aber wofür das ganze gut ist konnte mir google auch nicht so richtig sagen.

Action: : Wieso steht das in den Funktionen und was bewirkt es?

Quellcode

1
2
3
4
#if defined _myevents_included
  #endinput
#endif
#define _myevents_included

Für was ist das gut?