Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
23.08.2001, 21:01
DBug



Ahoi !

Also ich hab mal mir ne Timer Klasse gemacht (gutes tut übrigens *gg*). Da ich die für einen Singleplayer mod brauche sollen natürlich nur manche Level "auf Zeit" gespielt werden. Deshalb habe ich mir überlegt, das in ein Entity reinzupacken. Gibt es vielleicht irgentwie sowas wie ein Level_info-Entity oder so, das in jedem level drin ist, und dem ich dann nur eine membervar hinzufügen muss ?? Oder muss ich da ein komplett neues entity machen ?

--

zum Seitenanfang zum Seitenende Profil || Suche
001
23.08.2001, 21:18
Archangel



hmm.. nimm den worldspawn (CWorld), dann kannst du (mit entsprechendem fgd-eintrag) das zeitlimit unter map properties einstellen

--

Mar 01 01:10:13 <voice> jo
Mar 01 01:10:40 <voice> bis dann ^^
Mar 01 01:11:20 <Archangel> jo
**** ENDING LOGGING AT Tue Mar 1 01:58:13 2005

zum Seitenanfang zum Seitenende Profil || Suche
002
23.08.2001, 22:49
apfelkorn



schaumal bei CWorld::KeyValues. Da wird unter anderem abgefragt, welche Sky-Textur benutzt werden soll etc. Das kann man dann im WC - oh, sorry - in WC unter Map / Properities einstellen, vorausgesetzt, du hast es auch in deiner .fgd drin.

--

zum Seitenanfang zum Seitenende Profil || Suche
003
24.08.2001, 16:21
DBug



@Archangel: Yo, genau das hab ich gesucht, thx :) !

@apfelkorn: hää ? Trotzdem thx ;) !

--

zum Seitenanfang zum Seitenende Profil || Suche
004
26.08.2001, 15:57
DBug



Hmm, hatte jetzt mal wieder Zeit und hab da n bisschen dranrumgefummelt. Also in der fgd is der Eintrag drin und er funzt in WC. Jetzt hab ich in der Keyvalues (ahh, das meintest du also, apfelkorn ;)) nen extra 'else if'-Block, der den Eintrag behandelt:

Quellcode:
else if( FStrEq(pkvd->szKeyName, "TimeLimit") )
{
int timelimit = atoi(pkvd->szValue);
                         // Hier der send code hin
            }

Jetzt das Prob: Da wo der Kommentar ist muss noch code hin, der die var 'timelimit' zum Client sendet. Ich nehme an, das geht irgentwie mit diesem MESSAGE_BEGIN Krams, aber wie ??

--

zum Seitenanfang zum Seitenende Profil || Suche
005
26.08.2001, 16:28
TheTinySteini



Guck z.B. mal in das Infrarot-NVG-Tutorial von Prefect, da hat er ziemlich gut erklärt, wie das mit den Messages funktioniert (wenn halt auch in nem anderen Zusammenhang).

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
006
26.08.2001, 22:00
DBug



K, thx, das hab ich nun gemacht. VC++ macht auch keine Fehler, aber eine misteriöse Warnung:

"unsichere Operation: kein Wert vom Typ 'bool' erweitert auf Typ 'const int' kann mit der angegebenen Konstante übereinstimmen"

Das passiert bei folgendem code

Quellcode:
else if( FStrEq(pkvd->szKeyName, "TimeLimit") )
{
int MapHasTimelimit;
bTimerActive = false;


MapHasTimelimit = 120;  // MapHasTimelimit = atoi(pkvd->szValue);


if( !MapHasTimelimit == -1 )    // Map hat Zeitlimit
{
// Message für den client
MESSAGE_BEGIN( MSG_ONE, gmsgTimerActivated, NULL, pev );
    WRITE_BYTE( 1 );
MESSAGE_END( );

//Message für diese dll
bTimerActive = true;

}
else    // Map hat kein Zeitlimit
{
// Message für den client
MESSAGE_BEGIN( MSG_ONE, gmsgTimerActivated, NULL, pev );
    WRITE_BYTE( 0 );
MESSAGE_END( );

// Message für diese dll
bTimerActive = false;
}

pkvd->fHandled = TRUE;
}

(Da wo MapHasTimelimit = 120 (nur zum DBuggen) steht muss natürlich dann später der Kommentar hin)

Allerdings funzt das net. In der client.dll is aber ne funktion zum annehmen der message, und DECLARE_MESSAGE und HOOK_MESSAGE gibs auch... Irgentjemand ne idee ?

BTW: Is READ_BYTE und WRITE_BYTE für bool richtig ??

--


Dieser Beitrag wurde am 26.08.2001 um 22:01 von DBug bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
007
26.08.2001, 22:20
Retro



P.S.: Wo gibt es das Tutorial? :D

--

shielding people from their own stupidity is an evolutionary step backwards anyway.

/* God is dead!............Nietzsche */
/* Nietzsche is dead!......God */
/* Nietzsche is God!.......The Dead */

zum Seitenanfang zum Seitenende Profil || Suche
008
26.08.2001, 23:40
Mazze



Ich bin mir nicht sicher, ob das stimmt. Mach da lieber noch Klammern hin:
if( !(MapHasTimelimit == -1) )

oder einfach:
if(MapHasTimelimit >= 0)

--

BattleTech-MOD:
http://bthl.unitedgaming.net/


Dieser Beitrag wurde am 26.08.2001 um 23:41 von Mazze bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
009
27.08.2001, 20:58
DBug



Hmm, leider funzt es immer noch net. Das mit den Klammern bringt nix, und wenn ich das mit <= schreibe, dann kommt folgende Fehlermeldung:

warning C4804: '<=' : unsichere Verwendung des Typs 'bool' in einer Operation

Aber ich hab die var doch ausdrücklich als int deklariert...

--

zum Seitenanfang zum Seitenende Profil || Suche
010
27.08.2001, 22:24
Killing Me Softly



1. if(MapHasTimelimit >= 0) müsste ohne Warnung funktionieren. Schau mal nach, ob du u.U. ein '!' übersehen hast.
2. Nachdem du das Ganze fehlerfrei kompiliert hast, und ne Map startest, in dem bei 'worldspawn' auch das entsprechende KeyValue gesetzt wurde, wird sich HL mit nem sauberen Crash verabschieden. Begründung:
Quellcode:
// Message für den client
MESSAGE_BEGIN( MSG_ONE, gmsgTimerActivated, NULL, pev );
WRITE_BYTE( 1 );
MESSAGE_END( );

Hiermit schickst du die Message. Überleg aber mal ganz kurz an wenn du die Message eigentlich schickst. Richtig: CWorld (um exakt zu sein - ein Objekt der Klasse 'CWorld').
1. Lösungsansatz: statt MSG_ONE einfach MSG_ALL verwenden. Die Sache hat nur einen klitzekleinen Hacken. In dem Moment, in dem CWorld::KeyValue() aufgerufen wird, werden sich die wenigsten Clients bereits am Server eingeloggt haben. Also...
2. Lösungsansatz: timelimit irgendwo speichern z.B. in einer globalen Variablen (world.cpp wimmelt nur so von globalen Variablen, wobei mir persönlich das jedesmal die Tränen in die Augen steigen läßt) und in CBasePlayer::UpdateClientData() in dem 'if (m_fInitHUD)' - Block dann die Message versenden.

--

Der Horizont vieler Menschen ist ein Kreis mit Radius Null - und das nennen sie ihren Standpunkt.

zum Seitenanfang zum Seitenende Profil || Suche
011
28.08.2001, 15:46
DBug



Hmm, das ganze wird ja ein Singleplayermod, wird da die client.dll auch erst nach CWorld::KeyValue geladen ??

edit: Denn bis jetzt is HL nicht abgekackt...

--


Dieser Beitrag wurde am 28.08.2001 um 15:47 von DBug bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
012
28.08.2001, 18:19
Killing Me Softly



Das HL noch nicht gecrasht ist liegt imho daran, das du noch keine Map geladen hast, in der bei 'worldspawn' 'TimeLimit' gesetzt war. Sag bescheid, falls ich mich irren sollte.
Wie das Zeitverhalten bei nem Single-Player-Mod ist, kann ich nicht sagen. Ich würde mich aber nicht darauf verlassen d.h. auch wenn es jetzt, bei Dir funktionieren sollte heißt das noch lange nicht, das es nach ein paar weiteren Änderungen im Code (an ganz anderen Stellen) oder auf einem anderen Rechner ebenfalls funktioniert. Ich würde die Message auf jeden Falle erst dann senden, wenn ich weiss das der Client auch dazu bereit ist.

--

Der Horizont vieler Menschen ist ein Kreis mit Radius Null - und das nennen sie ihren Standpunkt.

zum Seitenanfang zum Seitenende Profil || Suche
013
28.08.2001, 19:27
DBug



lol, genau das is mir 1 Minute nach dem Posten auch eingefallen :) ! Also, du hast recht !

Übrigens funzt das mit den Klammern jetzt auch, ich muss das "!" also außerhalb der inneren Klammer machen...

Naja, dann muss ich das mit der globalen var wohl mal probieren, schade dass es nicht einfacher geht :) !

--

zum Seitenanfang zum Seitenende Profil || Suche
014
28.08.2001, 20:07
DBug



Also, ich habs jetzt grad mal geändert:

In der Keyvalue wird nur noch die globale variable iTimeLimit mit 120 (bzw. später mit dem aus Worldspawn gelesenen Wert) "gefüllt".

Der ganze Unterscheidungskrams findet in der player.cpp --> UpdateClientData
innerhalb des if(m_InitHud) Blocks statt. Da ist dann jedoch nur noch die Unterscheidung: "Wenn Timilimit_angeschaltet" fällig, ansonsten wird der block einfach ignoriert und keine message zum client geschickt. Dort muss ich dann also den Standard auf "TimeLimit AUS" setzen... Aber seht selbst ;):

Quellcode:

if(!(iTimeLimit == -1))
{
// Message für den client
MESSAGE_BEGIN( MSG_ONE, gmsgTimerActivated, NULL, pev );
    WRITE_BYTE( 1 );
MESSAGE_END( );

MESSAGE_BEGIN( MSG_ONE, gmsgTimer, NULL, pev);
WRITE_LONG( 60 - (gpGlobals->time - m_iRoundStartTime)); //heisst hier eine Runde dauert 60 Sekunden
MESSAGE_END();

if( (gpGlobals->time - m_iRoundStartTime) > 65)//eine neue Runde beginnt
{
m_iRoundStartTime = gpGlobals->time;
Spawn(); //nochmal spawnen
}
}

Die zweite message gehört zum Timer-Tut...

Jetzt das Prob: Wenn ich eine map starte, kommt: "Tried to create a message with a bogus message type (0)"...

Was hat das zu bedeuten ??

EDIT: ROFL !! Ich kann ja die message auch einsparen, da ich ja sowieso schon unterscheiden kann, ob die MapTimelimit hat oder nicht. Wenn keine gmsgTimer message in der client ankommt, muss das timelimit deaktiviert sein...Naja, wenigstens hab ich n bisschen was über messages gelernt :))

Könnte mir vielleicht trotzdem jemand sagen was der Fehler zu bedeuten hat ?

--


Dieser Beitrag wurde am 28.08.2001 um 20:11 von DBug bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
015
28.08.2001, 20:30
Killing Me Softly



Das heisst einfach nur, das du vergessen hast, die Message zu registrieren. In der player.cpp muss in der Funktion void LinkUserMessages( void ) sowas stehen wie:

gmsgTimerActivated = REG_USER_MSG("TimerActivated",1);
gmsgTimer = REG_USER_MSG("Timer",4);

Zu meiner Schande muss ich gestehen, dass ich nicht genau weiss, wie lange der Name sein darf ( 'TimerActivated in 'REG_USER_MSG()' ), ich weiss nur, das er nicht beliebig lang sein darf. Ich hab mir irgenwann einmal angewöhnt, nicht mehr als 10 Zeichen zu benutzen. Falls du also die oberen beiden Zeilen in deinem Code hast, dann würde ich mal einen kürzeren Namen für 'TimerActivated' nehmen (bzw. wie du schon gesagt hast, die Message ganz wegfallen lassen, da sie eigentlich nicht notwendig ist).

--

Der Horizont vieler Menschen ist ein Kreis mit Radius Null - und das nennen sie ihren Standpunkt.

zum Seitenanfang zum Seitenende Profil || Suche
016
28.08.2001, 21:11
Archangel



maximum is iirc 12 zeichen, wenns länger is gibs nen
"tried to create a message with a bogus message type (0)" error...

--

Mar 01 01:10:13 <voice> jo
Mar 01 01:10:40 <voice> bis dann ^^
Mar 01 01:11:20 <Archangel> jo
**** ENDING LOGGING AT Tue Mar 1 01:58:13 2005

zum Seitenanfang zum Seitenende Profil || Suche
017
29.08.2001, 16:26
DBug



Yo, das wars. Ich hatte die msg zwar registriert, aber war wohl zu lang. Allerdings habe ich ja die message sowieso ganz gestrichen, d.h. ich mache alles über die eine message, die schon beim Timer tut "dabei" war...

--

zum Seitenanfang zum Seitenende Profil || Suche
018
29.08.2001, 16:55
DBug



So, kaum ist ein Prob gelöst kommt das nächste:

Erstmal den code:

Quellcode:
---------# hl.dll => player.cpp => UpdateClientData #-----------------

if(!(iTimeLimit == -100))
{
ALERT( at_console, "HL.DLL: iTimeLimit = %d\n", iTimeLimit - (gpGlobals->time - m_iRoundStartTime));

MESSAGE_BEGIN( MSG_ONE, gmsgTimer, NULL, pev);
WRITE_LONG( iTimeLimit - (gpGlobals->time - m_iRoundStartTime)); //heisst hier eine Runde dauert 60 Sekunden
MESSAGE_END();

if( (gpGlobals->time - m_iRoundStartTime) > iTimeLimit + 3)//eine neue Runde beginnt
{
m_iRoundStartTime = gpGlobals->time;
Spawn(); //nochmal spawnen
}
}

--------------------------------------------------------------------------

------#client.dll => timer.cpp -------------------------------------------
...
int CHudTimer::MsgFunc_Timer( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
  m_iRoundTime = READ_LONG();
m_iFlags |= HUD_ACTIVE;

if(!(m_iRoundTime = -100))
{
m_iIsTimerActivated = 1;
}
else
{
m_iIsTimerActivated = 0;
}

return 1;
}




int CHudTimer::Draw( float flTime )
{
  
// if( !m_iIsTimerActivated == 0)
  {
int r, g, b;
UnpackRGB(r, g, b, RGB_WHITEISH);

if(m_iRoundTime > 0) //sicherstellen,dass keine negativen Werte auftreten
{
    gHUD.DrawHudNumber( 462, 68, DHN_2DIGITS | DHN_PREZERO, m_iRoundTime/60, r, g, b);
    gHUD.DrawHudString(511, 71, ScreenWidth, ":",r, g, b);
    gHUD.DrawHudNumber(522, 68, DHN_2DIGITS | DHN_PREZERO, m_iRoundTime%60, r, g, b);
}
else  //No time left...
{

     gHUD.DrawHudString((ScreenWidth/2-2)-53,ScreenHeight/2-6, ScreenWidth, "You took too long...", r, g, b); //s.o.
    gHUD.DrawHudNumber( 462, 68,DHN_2DIGITS | DHN_PREZERO, 0, r, g, b);//s.o.
    gHUD.DrawHudString(511, 71,ScreenWidth, ":", r, g, b); //s.o.
    gHUD.DrawHudNumber(522, 68,DHN_2DIGITS | DHN_PREZERO, 0, r, g, b);
}

  }
return 1;
}
...

--------------------------------------------------------------------------

So. Das problem ist, das die ganze Zeit "You took too long" angezeigt wird, also der "else" block in der draw-funktion ausgeführt wird. Durch Con_Printf hab ich rausgefunden, das diese Funktion richtig arbeitet, da m_iRoundTime den Wert -100 hat. Allerdings darf das nicht sein, da ich iTimeLimit (serverseitig) zu DBug zwecken mit 90 initialisiert habe.

Also hab ich über die "alert" Zeile rausgekriegt, das iTimelimit auch wirklich nicht -100 ist, und in der hl.dll der auch alles richtig abläuft.
Denn es steht zwar wie gesagt auf dem HUD "00:00" für Zeit, aber nach 90 secs spawnt man neu.

==>> Also denke ich mir muss der Fehler vielleicht bei den messages liegen, dass die diesen Wert nicht korrekt übermitteln. Aber was muss ich ändern ???

(Hinweis: Die messages sind registriert, und sie funzten vorher auch...)

thx :) !

--


Dieser Beitrag wurde am 29.08.2001 um 16:57 von DBug bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche