Server Gateways

 

OK this is a quick mod I (Gary Tunstall) made.

 

The mod lets the server admin create 'special' teleporters in a map. These 'gateways' transport a player to a new server when the player walks on them and stays there for 3 seconds. They also display info (name, name of MOD running, short description) about the target server when the player stands near them.

It is a server side mod not requiring the clients (players) to download anything

 

I have been a busy bunny and I am releasing the source.

Well kind of...

... I am actually releasing a txt file I made documenting the changes I made (in code form).

Its can't be compiled but if someone knew how to code they could make a working copy out of it.

I am releasing it as most of my knowlege came from others source and tutorials (and glitter).

I feel it is only fair I release my source.

However I don't want anyone just nicking it and say its theirs!

You can use it in a mod as long as you mention me someone is some documentation (ie in a credits section or something) and if you email me and tell me so I can have a look at it in use.

Of cause at the moment it is probably impossible to understand what my changes mean as there are no comment

 

Line numbers may be out by serveral number due to comments and linefeeds

 

g_main.c

--------

56: vars at top: after cvar_t *sv_maplist;

cvar_t  *save_gateways;

 

q_shared.h

----------

992: in // player_state->stats[] indexes: after #define STAT_SPECTATOR 17

#define STAT_NAME                        18

#define STAT_MOD              19

#define STAT_DESCRIPTION          20

#define STAT_ADDRESS                  21

 

g_local.h

---------

536: in vars in middle: after extern cvar_t *sv_maplist;

extern  cvar_t  *save_gateways;

944: in struct gclient_s: after float respawn_time;

            float                 gateway_mes_time;

            int                                gateway;

995: in struct edict_s: after char *message;

            char                 *servername;

            char                 *serverdescription;

            char                 *servermod;

could have used - but not sure if in use else where

            char                 *pathtarget;

            char                 *deathtarget;

            char                 *combattarget;

 

p_hud.c

-------

505: in void G_SetStats (edict_t *ent): after ent->client->ps.stats[STAT_SPECTATOR] = 0;

            if (ent->client->gateway)

                        {

                        ent->client->ps.stats[STAT_NAME]              = CS_GENERAL+(ent->client->gateway*4)  ;

                        ent->client->ps.stats[STAT_MOD]                            = CS_GENERAL+(ent->client->gateway*4)+1;

                        ent->client->ps.stats[STAT_DESCRIPTION]            = CS_GENERAL+(ent->client->gateway*4)+2;

                        ent->client->ps.stats[STAT_ADDRESS]                   = CS_GENERAL+(ent->client->gateway*4)+3;

                        if (ent->client->gateway_mes_time<level.time)

                                    {

                                    ent->client->gateway=0;

                                    }

                        }

            else

                        {

                        ent->client->ps.stats[STAT_NAME]              = 0;

                        ent->client->ps.stats[STAT_MOD]                            = 0;

                        ent->client->ps.stats[STAT_DESCRIPTION]            = 0;

                        ent->client->ps.stats[STAT_ADDRESS]                   = 0;

                        }

 

g_save.c

--------

22: in field_t fields[] = {: after {"message", FOFS(message), F_LSTRING},

            {"servername", FOFS(servername), F_LSTRING},

            {"serverdescription", FOFS(serverdescription), F_LSTRING},

            {"servermod", FOFS(servermod), F_LSTRING},

190: in void InitGame (void): after sv_maplist = gi.cvar ("sv_maplist", "", 0);

            save_gateways = gi.cvar ("allow_save_gateway", "0", CVAR_SERVERINFO);

 

g_cmds.c

--------

884: in file (it is a function): after gi.cprintf(ent, PRINT_HIGH, "%s", text); } (from void Cmd_PlayerList_f(edict_t *ent))

char     *vtos_nob (vec3_t v)

{

            static    int                    index_nob;

            static    char     str_nob[8][32];

            char     *s;

 

            // use an array so that multiple vtos won't collide

            s = str_nob[index_nob];

            index_nob = (index_nob + 1)&7;

 

            Com_sprintf (s, 32, "%i %i %i", (int)v[0], (int)v[1], (int)v[2]);

 

            return s;

}

 

void save_tele_to_file(edict_t *ent)

{

FILE *outFile;

cvar_t  *game_cvar;

 

if (save_gateways->value)

{

if (!(gi.argv(1))||(strcmp("",gi.argv(1))==0))

            {

            gi.cprintf(ent,PRINT_HIGH,"Sorry no server destination aborting\n");

            return;

            }

            game_cvar = gi.cvar("game", "", 0);

 

            if (outFile = fopen(va("%s/ent/%s.ent",game_cvar->string,level.mapname), "a"))

                        {

                        gi.dprintf("%s opened\n",va("%s/ent/%s.ent",game_cvar->string,level.mapname));

                        fprintf(outFile, va("{\n\"classname\" \"misc_teleporter\"\n\"origin\" \"%s\"\n\"target\" \"dest\"\n",vtos_nob(ent->s.origin)));

                        if ((gi.argv(1))&&!(strcmp("",gi.argv(1))==0))

                                    {

                                    fprintf(outFile, va("\"map\" \"%s\"\n",gi.argv(1)));

                                    }

                        if ((gi.argv(2))&&!(strcmp("",gi.argv(2))==0))

                                    {

                                    fprintf(outFile, va("\"servername\" \"%s\"\n",gi.argv(2)));

                                    }

                        if ((gi.argv(3))&&!(strcmp("",gi.argv(3))==0))

                                    {

                                    fprintf(outFile, va("\"serverdescription\" \"%s\"\n",gi.argv(3)));

                                    }

                        if ((gi.argv(4))&&!(strcmp("",gi.argv(4))==0))

                                    {

                                    fprintf(outFile, va("\"servermod\" \"%s\"\n",gi.argv(4)));

                                    }

                        if ((gi.argv(5))&&!(strcmp("",gi.argv(5))==0))

                                    {

                                    fprintf(outFile, va("\"message\" \"%s\"\n",gi.argv(5)));

                                    }

                        fprintf(outFile,"}\n");

                        fclose(outFile);

                        gi.dprintf("%s closed\n",va("%s/ent/%s.ent",game_cvar->string,level.mapname));

                        gi.cprintf(ent,PRINT_HIGH,"Saved new site restart map to see effect\n");

                        }

            else

                        {

                        gi.dprintf("%s not opened\n",va("%s/ent/%s.ent",game_cvar->string,level.mapname));

                        gi.cprintf(ent,PRINT_HIGH,"Sorry saving teleports broke!\n");

                        }

}

else

{

gi.cprintf(ent,PRINT_HIGH,"Sorry saving teleports not enabled with allow_save_gateway\n");

}

 

}

1042: in void ClientCommand (edict_t *ent):after Cmd_PlayerList_f(ent);

            else if (Q_stricmp(cmd, "save_gateway") == 0)

                        save_tele_to_file(ent);

 

g_spawn.c

---------

509: in void SpawnEntities (char *mapname, char *entities, char *spawnpoint): after float skill_level;

            int                    inhibit2;

            FILE    *ent_file;

            char     gaztemp[70000],*gazents;

            char     gazbuf[101];

            cvar_t  *game_cvar;

 

            game_cvar = gi.cvar("game", "", 0);

539: in void SpawnEntities (char *mapname, char *entities, char *spawnpoint): after g_edicts[i+1].client = game.clients + i;

strcpy(gaztemp,"");

 

if (ent_file = fopen(va("%s/ent/%s.ent",game_cvar->string,mapname), "r"))

{

            gi.dprintf("Ents: %s ",va("%s/ent/%s.ent",game_cvar->string,mapname));

 

            while ((fgets(gazbuf,100,ent_file)) != NULL)

                                    {

                                    strcat(gaztemp, gazbuf);

                                    }

 

            fclose(ent_file);

            gi.dprintf("read\n");

}

else

{

gi.dprintf("Ents: %s not read\n",va("%s/ent/%s.ent",game_cvar->string,mapname));

}

616: in void SpawnEntities (char *mapname, char *entities, char *spawnpoint): after gi.dprintf ("%i entities inhibited\n", inhibit);

            gazents=gaztemp;

            inhibit2 = 0;

 

// parse ents

            while (1)

            {

                        // parse the opening brace

                        com_token = COM_Parse (&gazents);

                        if (!gazents)

                                    break;

                        if (com_token[0] != '{')

                                    gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

 

                        if (!ent)

                                    ent = g_edicts;

                        else

                                    ent = G_Spawn ();

                        gazents = ED_ParseEdict (gazents, ent);

 

                        // yet another map hack

                        if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))

                                    ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

 

                        // remove things (except the world) from different skill levels or deathmatch

                        if (ent != g_edicts)

                        {

                                    if (deathmatch->value)

                                    {

                                                if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH )

                                                {

                                                            G_FreeEdict (ent);

                                                            inhibit2++;

                                                            continue;

                                                }

                                    }

                                    else

                                    {

                                                if ( // ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) ||

                                                            ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||

                                                            ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||

                                                            (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))

                                                            )

                                                            {

                                                                        G_FreeEdict (ent);

                                                                        inhibit2++;

                                                                        continue;

                                                            }

                                    }

 

                                    ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH);

                        }

 

                        ED_CallSpawn (ent);

 

            }

 

            if (inhibit2) gi.dprintf ("%i entities from .ent inhibited\n", inhibit2);

772: in char *single_statusbar =: after "          pic       11 " "endif "

"if 18 "

  "xv 10 "

  "yv 40 "

  "string2 \"This teleporter goes to another server\" "

 

  "xv 50 "

  "yv 60 "

  "string2 \"Name\" "

  "yv 70 "

  "string2 \"MOD\" "

  "yv 80 "

  "string2 \"Description\" "

  "yv 90 "

  "string2 \"Address\" "

 

  "xv 150 "

  "yv 60 "

  "stat_string 18 "

  "yv 70 "

  "stat_string 19 "

  "yv 80 "

  "stat_string 20 "

  "yv 90 "

  "stat_string 21 "

"endif "

877: in char *dm_statusbar =: after "stat_string 16 " "endif "

"if 18 "

  "xv 10 "

  "yv 40 "

  "string2 \"This teleporter goes to another server\" "

 

  "xv 50 "

  "yv 60 "

  "string2 \"Name\" "

  "yv 70 "

  "string2 \"MOD\" "

  "yv 80 "

  "string2 \"Description\" "

  "yv 90 "

  "string2 \"Address\" "

 

  "xv 150 "

  "yv 60 "

  "stat_string 18 "

  "yv 70 "

  "stat_string 19 "

  "yv 80 "

  "stat_string 20 "

  "yv 90 "

  "stat_string 21 "

"endif "

 

g_misc.c

--------

1764: in file (it is a funtion): after //=================================================================================

replace the whole of void teleporter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)

with

void teleporter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)

{

            edict_t             *dest;

            int                                i;

 

if(self->owner->map)

{

            if (other->client)

            {

            if (level.time > (self->owner->delay+1))

                        {

                        self->owner->delay=level.time;

                        self->owner->wait=level.time;  //                   reseting count

 

                        gi.cprintf (other, PRINT_HIGH, "Wait 3 secs to goto \"%s\"\n", self->owner->servername);

                        return;

                        }

                        else

                        {

                        if (level.time > (self->owner->wait+3))

                                    {

                                    gi.cprintf (other,PRINT_MEDIUM, "Teleporting to %s\n",self->owner->servername);

                                    if (self->owner->message)

                                                {

                                                gi.cprintf (other,PRINT_MEDIUM, "%s\n",self->owner->message);

                                                }

                                    gi.WriteByte (svc_stufftext);

                                    gi.WriteString (va("connect %s\n",self->owner->map));

                                    gi.unicast(other, true);

                                    gi.bprintf (PRINT_HIGH, "%s went to %s\n", other->client->pers.netname,self->owner->servername);

                                    self->owner->delay=level.time;

                                    self->owner->wait=level.time;  //                   reseting count

                                    }

                                    else

                                    {

                                    self->owner->delay=level.time;

//                      gi.dprintf("delay %f  wait %f\n",level.time-self->owner->delay,level.time-self->owner->wait);

                                    return;

                                    }

                        }

            }

}

else

{

 

            if (!other)

                        return;

            dest = G_Find (NULL, FOFS(targetname), self->target);

            if (!dest)

            {

                        gi.dprintf ("Couldn't find destination\n");

                        return;

            }

 

            // unlink to make sure it can't possibly interfere with KillBox

            gi.unlinkentity (other);

 

            VectorCopy (dest->s.origin, other->s.origin);

            VectorCopy (dest->s.origin, other->s.old_origin);

            other->s.origin[2] += 10;

 

            // clear the velocity and hold them in place briefly

            VectorClear (other->velocity);

            if (other->client)

            {

            other->client->ps.pmove.pm_time = 160>>3;             // hold time

            other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;

            }

 

            // draw the teleport splash at source and on the player

            self->owner->s.event = EV_PLAYER_TELEPORT;

            other->s.event = EV_PLAYER_TELEPORT;

 

            // set angles

            if (other->client)

            {

            for (i=0 ; i<3 ; i++)

            {

                        other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(dest->s.angles[i] - other->client->resp.cmd_angles[i]);

            }

            }

 

            VectorClear (other->s.angles);

            if (other->client)

            {

            VectorClear (other->client->ps.viewangles);

            VectorClear (other->client->v_angle);

            }

            // kill anything at the destination

            KillBox (other);

 

            gi.linkentity (other);

}

}

1859: in file (it is a function): after gi.linkentity (other); } }

void teleporter_msg_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)

{

if (!other->client)

            return;

 

            other->client->gateway=self->owner->count;

            other->client->gateway_mes_time=level.time+3;

}

 

int no_gateways=0;

1876: in void SP_misc_teleporter (edict_t *ent): after edict_t *trig;

            edict_t             *trig2;

1885: in void SP_misc_teleporter (edict_t *ent): after return; }

            if ((ent->message) && (!ent->map))

                        {

                        ent->map = ent->message;

                        ent->message = NULL;

                        gi.dprintf("Target server was message (error in map) %s\n",ent->map);

                        }

 

            if (ent->map)

                        {

                                    if (!ent->servername)

                                                {

                                                ent->servername = ent->map;

                                                }

                                    if (!ent->serverdescription)

                                                {

                                                ent->serverdescription = "None";

                                                }

                                    if (!ent->servermod)

                                                {

                                                ent->servermod = "Not specified";

                                                }

                                    no_gateways++;

                                    ent->count=no_gateways;

                                    gi.configstring (CS_GENERAL+(no_gateways*4)  , va("%s", ent->servername) );

                                    gi.configstring (CS_GENERAL+(no_gateways*4)+1, va("%s", ent->servermod) );

                                    gi.configstring (CS_GENERAL+(no_gateways*4)+2, va("%s", ent->serverdescription) );

                                    gi.configstring (CS_GENERAL+(no_gateways*4)+3, va("%s", ent->map) );

                        }

1934: in void SP_misc_teleporter (edict_t *ent): after gi.linkentity (trig);

            trig2 = G_Spawn ();

            trig2->touch = teleporter_msg_touch;

            trig2->solid = SOLID_TRIGGER;

            trig2->target = ent->target;

            trig2->owner = ent;

            VectorCopy (ent->s.origin, trig2->s.origin);

            VectorSet (trig2->mins, -75, -75, -16);

            VectorSet (trig2->maxs, 75, 75, 32);

            gi.linkentity (trig2);