diff --git a/source/src/client.cpp b/source/src/client.cpp index f3860c1f..6e3a549e 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -1,606 +1,309 @@ // client.cpp, mostly network related client game code - - #include "cube.h" - - ENetHost *clienthost = NULL; - int connecting = 0; - int connattempts = 0; - int disconnecting = 0; - int clientnum = -1; // our client id in the game - bool c2sinit = false; // whether we need to tell the other clients our stats - - int getclientnum() { return clientnum; }; - - bool multiplayer() - { - // check not correct on listen server? - if(clienthost) conoutf("operation not available in multiplayer"); - return clienthost!=NULL; - }; - - bool allowedittoggle() - { - bool allow = !clienthost || gamemode==1; - if(!allow) conoutf("editing in multiplayer requires coopedit mode (1)"); - return allow; - }; - - VARF(rate, 0, 0, 25000, if(clienthost && (!rate || rate>1000)) enet_host_bandwidth_limit (clienthost, rate, rate)); - - void throttle(); - - VARF(throttle_interval, 0, 5, 30, throttle()); - VARF(throttle_accel, 0, 2, 32, throttle()); - VARF(throttle_decel, 0, 2, 32, throttle()); - - void throttle() - { - if(!clienthost || connecting) return; - assert(ENET_PEER_PACKET_THROTTLE_SCALE==32); - enet_peer_throttle_configure(clienthost->peers, throttle_interval*1000, throttle_accel, throttle_decel); - }; - - void newname(char *name) { c2sinit = false; strn0cpy(player1->name, name, 16); }; - void newteam(char *name) { c2sinit = false; strn0cpy(player1->team, name, 5); }; - - COMMANDN(team, newteam, ARG_1STR); - COMMANDN(name, newname, ARG_1STR); - - void connects(char *servername) - { - disconnect(1); // reset state - addserver(servername); - - - conoutf("attempting to connect to %s", (int) servername); - + conoutf("attempting to connect to %s", servername); ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; - if(enet_address_set_host(&address, servername) < 0) - { - - conoutf("could not resolve server %s", (int) servername); - + conoutf("could not resolve server %s", servername); return; - }; - - clienthost = enet_host_create(NULL, 1, rate, rate); - - if(clienthost) - { - enet_host_connect(clienthost, &address, 1); - enet_host_flush(clienthost); - connecting = lastmillis; - connattempts = 0; - } - else - { - conoutf("could not connect to server"); - disconnect(); - }; - }; - - void disconnect(int onlyclean, int async) - { - if(clienthost) - { - if(!connecting && !disconnecting) - { - enet_peer_disconnect(clienthost->peers); - enet_host_flush(clienthost); - disconnecting = lastmillis; - }; - if(clienthost->peers->state != ENET_PEER_STATE_DISCONNECTED) - { - if(async) return; - enet_peer_reset(clienthost->peers); - }; - enet_host_destroy(clienthost); - }; - - if(clienthost && !connecting) conoutf("disconnected"); - clienthost = NULL; - connecting = 0; - connattempts = 0; - disconnecting = 0; - clientnum = -1; - c2sinit = false; - player1->lifesequence = 0; - loopv(players) zapdynent(players[i]); - - localdisconnect(); - - if(!onlyclean) { stop(); localconnect(); }; - }; - - void trydisconnect() - { - if(!clienthost) - { - conoutf("not connected"); - return; - }; - if(connecting) - { - conoutf("aborting connection attempt"); - disconnect(); - return; - }; - conoutf("attempting to disconnect..."); - disconnect(0, !disconnecting); - }; - - string ctext; - void toserver(char *text) { conoutf("%s:\f %s", (int)player1->name, (int)text); strn0cpy(ctext, text, 80); }; - void echo(char *text) { conoutf("%s", (int)text); }; - - COMMAND(echo, ARG_VARI); - COMMANDN(say, toserver, ARG_VARI); - COMMANDN(connect, connects, ARG_1STR); - COMMANDN(disconnect, trydisconnect, ARG_NONE); - - // collect c2s messages conveniently - - vector messages; - - void addmsg(int rel, int num, int type, ...) - { - if(demoplayback) return; - if(num!=msgsizelookup(type)) { sprintf_sd(s)("inconsistant msg size for %d (%d != %d)", type, num, msgsizelookup(type)); fatal(s); }; - ivector &msg = messages.add(); - msg.add(num); - msg.add(rel); - msg.add(type); - va_list marker; - va_start(marker, type); - loopi(num-1) msg.add(va_arg(marker, int)); - va_end(marker); - }; - - void server_err() - { - conoutf("server network error, disconnecting..."); - disconnect(); - }; - - int lastupdate = 0, lastping = 0; - string toservermap; - bool senditemstoserver = false; // after a map change, since server doesn't have map data - - string clientpassword; - void password(char *p) { strcpy_s(clientpassword, p); }; - COMMAND(password, ARG_1STR); - - bool netmapstart() { senditemstoserver = true; return clienthost!=NULL; }; - - void initclientnet() - { - ctext[0] = 0; - toservermap[0] = 0; - clientpassword[0] = 0; - newname("unnamed"); - newteam("red"); - }; - - void sendpackettoserv(void *packet) - { - if(clienthost) { enet_host_broadcast(clienthost, 0, (ENetPacket *)packet); enet_host_flush(clienthost); } - else localclienttoserver((ENetPacket *)packet); - } - - void c2sinfo(dynent *d) // send update to the server - { - if(clientnum<0) return; // we haven't had a welcome message from the server yet - if(lastmillis-lastupdate<40) return; // don't update faster than 25fps - ENetPacket *packet = enet_packet_create (NULL, MAXTRANS, 0); - uchar *start = packet->data; - uchar *p = start+2; - bool serveriteminitdone = false; - if(toservermap[0]) // suggest server to change map - { // do this exclusively as map change may invalidate rest of update - packet->flags = ENET_PACKET_FLAG_RELIABLE; - putint(p, SV_MAPCHANGE); - sendstring(toservermap, p); - toservermap[0] = 0; - putint(p, nextmode); - } - else - { - putint(p, SV_POS); - putint(p, clientnum); - putint(p, (int)(d->o.x*DMF)); // quantize coordinates to 1/16th of a cube, between 1 and 3 bytes - putint(p, (int)(d->o.y*DMF)); - putint(p, (int)(d->o.z*DMF)); - putint(p, (int)(d->yaw*DAF)); - putint(p, (int)(d->pitch*DAF)); - putint(p, (int)(d->roll*DAF)); - putint(p, (int)(d->vel.x*DVF)); // quantize to 1/100, almost always 1 byte - putint(p, (int)(d->vel.y*DVF)); - putint(p, (int)(d->vel.z*DVF)); - // pack rest in 1 byte: strafe:2, move:2, onfloor:1, state:3 - putint(p, (d->strafe&3) | ((d->move&3)<<2) | (((int)d->onfloor)<<4) | ((editmode ? CS_EDITING : d->state)<<5) ); - - + if(gun_changed) + { + putint(p, SV_WEAPCHANGE); + putint(p, player1->gunselect); + gun_changed = false; + } if(senditemstoserver) - { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - putint(p, SV_ITEMLIST); - if(!m_noitems) putitems(p); - putint(p, -1); - senditemstoserver = false; - serveriteminitdone = true; - }; - if(ctext[0]) // player chat, not flood protected for now - { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - putint(p, SV_TEXT); - sendstring(ctext, p); - ctext[0] = 0; - }; - if(!c2sinit) // tell other clients who I am - { - packet->flags = ENET_PACKET_FLAG_RELIABLE; - c2sinit = true; - putint(p, SV_INITC2S); - sendstring(player1->name, p); - sendstring(player1->team, p); - putint(p, player1->lifesequence); - }; - loopv(messages) // send messages collected during the previous frames - { - ivector &msg = messages[i]; - if(msg[1]) packet->flags = ENET_PACKET_FLAG_RELIABLE; - loopi(msg[0]) putint(p, msg[i+2]); - }; - messages.setsize(0); - if(lastmillis-lastping>250) - { - putint(p, SV_PING); - putint(p, lastmillis); - lastping = lastmillis; - }; - }; - *(ushort *)start = ENET_HOST_TO_NET_16(p-start); - enet_packet_resize(packet, p-start); - incomingdemodata(start, p-start, true); - if(clienthost) { enet_host_broadcast(clienthost, 0, packet); enet_host_flush(clienthost); } - else localclienttoserver(packet); - lastupdate = lastmillis; - if(serveriteminitdone) loadgamerest(); // hack - }; - - void gets2c() // get updates from the server - { - ENetEvent event; - if(!clienthost) return; - if(connecting && lastmillis/3000 > connecting/3000) - { - conoutf("attempting to connect..."); - connecting = lastmillis; - ++connattempts; - if(connattempts > 3) - { - conoutf("could not connect to server"); - disconnect(); - return; - }; - }; - while(clienthost!=NULL && enet_host_service(clienthost, &event, 0)>0) - switch(event.type) - { - case ENET_EVENT_TYPE_CONNECT: - conoutf("connected to server"); - connecting = 0; - throttle(); - break; - - case ENET_EVENT_TYPE_RECEIVE: - if(disconnecting) conoutf("attempting to disconnect..."); - else localservertoclient(event.packet->data, event.packet->dataLength); - enet_packet_destroy(event.packet); - break; - - case ENET_EVENT_TYPE_DISCONNECT: - if(disconnecting) disconnect(); - else server_err(); - return; - } - }; - - diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index adcdd23a..963b3835 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -69,8 +69,11 @@ void renderclients() renderclient(d, isteam(player1->team, d->team), "playermodels/terrorist", false, 1.4f); } - sprintf_sd(vwep)("weapons/%s/world", hudgunnames[d->gunselect]); - renderclient(d, isteam(player1->team, d->team), vwep, true, 1.4f); + if(d->gunselect>0 && d->gunselectgunselect]); + renderclient(d, isteam(player1->team, d->team), vwep, true, 1.4f); + }; }; if(player1->state==CS_DEAD) { diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index 9f09a28d..8245426c 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -1,1191 +1,599 @@ // clientgame.cpp: core game related stuff - - #include "cube.h" - #define sleep my_sleep - int nextmode = 0; // nextmode becomes gamemode after next map load - VAR(gamemode, 1, 0, 0); - - void mode(int n) { addmsg(1, 2, SV_GAMEMODE, nextmode = n); }; - COMMAND(mode, ARG_1INT); - - bool intermission = false; - - dynent *player1 = newdynent(); // our client - dvector players; // other clients - - vector physents; - - VAR(sensitivity, 0, 10, 1000); - VAR(sensitivityscale, 1, 1, 100); - VAR(invmouse, 0, 0, 1); - - int lastmillis = 0; - int curtime; - string clientmap; - - extern int framesinmap; - - char *getclientmap() { return clientmap; }; - - void resetmovement(dynent *d) - { - d->k_left = false; - d->k_right = false; - d->k_up = false; - d->k_down = false; - d->jumpnext = false; - d->strafe = 0; - d->move = 0; - }; - - void spawnstate(dynent *d) // reset player state not persistent accross spawns - { - resetmovement(d); - d->vel.x = d->vel.y = d->vel.z = 0; - d->onfloor = false; - d->timeinair = 0; - d->health = 100; - d->armour = 0; - //d->hasarmour = false; - //d->armourtype = A_BLUE; - //d->quadmillis = 0; - d->gunselect = GUN_PISTOL; - d->mag[6]=10; - d->gunwait = 0; - d->attacking = false; - d->lastaction = 0; - - - radd(d); - - - //loopi(NUMGUNS) if(d->nextprimary!=i) d->ammo[i] = 0; - //d->mag[GUN_KNIFE] = 1; - //equp with default pistol - - //d->mag[GUN_PISTOL] = 8; - //if(d->nextprimary!=GUN_PISTOL) - // d->ammo[GUN_PISTOL] = 16; - //else - // d->ammo[GUN_PISTOL] = 32; - //temp for testing guns - //d->ammo[GUN_SHOTGUN] = 100; - //d->ammo[GUN_SUBGUN] = 400; - //d->ammo[GUN_SNIPER] = 100; - //d->ammo[GUN_ASSULT] = 400; - - //end tmp - - /* - if(m_noitems) - { - d->gunselect = GUN_RIFLE; - d->armour = 0; - if(m_noitemsrail) - { - d->health = 1; - d->ammo[GUN_RIFLE] = 100; - } - else - { - if(gamemode==12) { d->gunselect = GUN_FIST; return; }; // eihruls secret "instafist" mode - d->health = 256; - if(m_tarena) - { - int gun1 = rnd(4)+1; - baseammo(d->gunselect = gun1); - for(;;) - { - int gun2 = rnd(4)+1; - if(gun1!=gun2) { baseammo(gun2); break; }; - }; - } - else if(m_arena) // insta arena - { - d->ammo[GUN_RIFLE] = 100; - } - else // efficiency - { - loopi(4) baseammo(i+1); - d->gunselect = GUN_CG; - }; - d->ammo[GUN_CG] /= 2; - }; - } - else - { - d->ammo[GUN_SG] = 5; - }; - */ - }; - - dynent *newdynent() // create a new blank player or monster - { - dynent *d = (dynent *)gp()->alloc(sizeof(dynent)); - d->o.x = 0; - d->o.y = 0; - d->o.z = 0; - d->yaw = 270; - d->pitch = 0; - d->roll = 0; - d->maxspeed = 16; //16 max speed, 14 max with armour - d->outsidemap = false; - d->inwater = false; - d->radius = 1.1f; - d->eyeheight = 4.25f; - d->aboveeye = 0.7f; - d->frags = 0; - d->plag = 0; - d->ping = 0; - d->lastupdate = lastmillis; - d->enemy = NULL; - d->monsterstate = 0; - d->name[0] = d->team[0] = 0; - d->blocked = false; - d->lifesequence = 0; - d->state = CS_ALIVE; - d->shots = 0; - d->reloading = false; - d->nextprimary = 1; - d->hasarmour = false; - - d->bounce = false; - spawnstate(d); - return d; - }; - void respawnself() - { - spawnplayer(player1); - showscores(false); - }; - - void respawn() - { - if(player1->state==CS_DEAD) - { - player1->attacking = false; - if(m_arena) { conoutf("waiting for new round to start..."); return; }; - respawnself(); - }; - }; - - void arenacount(dynent *d, int &alive, int &dead, char *&lastteam, char *&lastname, bool &oneteam) - //void arenacount(dynent *d, int &alive, int &dead, char *&lastteam, bool &oneteam) - { - if(d->state!=CS_DEAD) - { - alive++; - if(lastteam && strcmp(lastteam, d->team)) oneteam = false; - lastteam = d->team; - lastname = d->name; - } - else - { - dead++; - }; - }; - - int arenarespawnwait = 0; - int arenadetectwait = 0; - - void arenarespawn() - { - if (!m_arena) return; - - if(arenarespawnwait) - { - if(arenarespawnwait0 && (alive<=1 || (m_teammode && oneteam))) - { - conoutf("arena round is over! next round in 5 seconds..."); - if(alive) - { - if(m_teammode) - conoutf("team %s has won the round", (int)lastteam); - else - conoutf("%s is the survior!", (int)lastname); - } - else conoutf("everyone died!"); - arenarespawnwait = lastmillis+5000; - arenadetectwait = lastmillis+10000; - player1->roll = 0; - }; - }; - }; - - - void checkquad(int time) - { - /* if(player1->quadmillis && (player1->quadmillis -= time)<0) - { - player1->quadmillis = 0; - playsoundc(S_PUPOUT); - conoutf("quad damage is over"); - }; - */ - }; - - //generic function to check all kinds of crazy gamemode specific things - void checkgame(int time) - { - - //allow faster movements when editing - /* if (editmode) - { - player1->maxspeed=22; - return; - } - else //otherwise max speed is 16 and 14 with armour - { - if(player1->armour>50) - player1->maxspeed = 14; - if(player1->armour>0) - player1->maxspeed = 15; - player1->maxspeed = 16; - }; - */ - - //force to a team if team mode - if (m_teammode) - { - if (strcmp(player1->team,"T") && strcmp(player1->team,"CT")) - { - player1->state = CS_DEAD; - //conoutf("set team to T or CT to joing game"); - if (rnd(2)<1) strcpy_s(player1->team,"T"); - else strcpy_s(player1->team,"CT"); - } - - //add checks here to force-drop flag if switching team with flag - - //add checks for end conditions of ctf - }; - - - //reset zoom if dead - - //etc - //checkquad(time); - - if (player1->state==CS_DEAD) - { - player1->primary = player1->nextprimary; - } - }; - - void zapdynent(dynent *&d) - { - if(d) gp()->dealloc(d, sizeof(dynent)); - d = NULL; - }; - - extern int democlientnum; - - void otherplayers() - { - loopv(players) if(players[i]) - { - const int lagtime = lastmillis-players[i]->lastupdate; - if(lagtime>1000 && players[i]->state==CS_ALIVE) - { - players[i]->state = CS_LAGGED; - continue; - }; - if(lagtime && players[i]->state != CS_DEAD && (!demoplayback || i!=democlientnum)) moveplayer(players[i], 2, false); // use physics to extrapolate player position - }; - }; - - extern void explode_nade(physent *i); - - void mphysents() - { - loopv(physents) if(physents[i]) - { - physent *p = physents[i]; - if(p->throwed) moveplayer(p, 2, false); - if(lastmillis - p->millis >= p->lifetime) - { - explode_nade(physents[i]); - physents.remove(i); - i--; - }; - }; - }; - - int sleepwait = 0; - string sleepcmd; - void sleep(char *msec, char *cmd) { sleepwait = atoi(msec)+lastmillis; strcpy_s(sleepcmd, cmd); }; - COMMAND(sleep, ARG_2STR); - - void updateworld(int millis) // main game update loop - { - if(lastmillis) - { - curtime = millis - lastmillis; - if(sleepwait && lastmillis>sleepwait) { execute(sleepcmd); sleepwait = 0; }; - physicsframe(); - checkgame(curtime); - //if(m_arena) arenarespawn(); - arenarespawn(); - moveprojectiles((float)curtime); - demoplaybackstep(); - if(!demoplayback) - { - if(getclientnum()>=0) shoot(player1, worldpos); // only shoot when connected to server - gets2c(); // do this first, so we have most accurate information when our player moves - }; - mphysents(); - otherplayers(); - if(!demoplayback) - { - //put game mode extra call here - if(player1->state==CS_DEAD) - { - if(lastmillis-player1->lastaction<2000) - { - player1->move = player1->strafe = 0; - moveplayer(player1, 10, false); - }; - } - else if(!intermission) - { - moveplayer(player1, 20, true); - checkitems(); - }; - c2sinfo(player1); // do this last, to reduce the effective frame lag - }; - }; - lastmillis = millis; - }; - - void entinmap(dynent *d) // brute force but effective way to find a free spawn spot in the map - { - loopi(100) // try max 100 times - { - float dx = (rnd(21)-10)/10.0f*i; // increasing distance - float dy = (rnd(21)-10)/10.0f*i; - d->o.x += dx; - d->o.y += dy; - if(collide(d, true, 0, 0)) return; - d->o.x -= dx; - d->o.y -= dy; - }; - conoutf("can't find entity spawn spot! (%d, %d)", (int)d->o.x, (int)d->o.y); - // leave ent at original pos, possibly stuck - }; - - int spawncycle = -1; - int fixspawn = 2; - - void spawnplayer(dynent *d) // place at random spawn. also used by monsters! - { + if(d==player1) gun_changed=true; int r = fixspawn-->0 ? 4 : rnd(10)+1; - loopi(r) spawncycle = findentity(PLAYERSTART, spawncycle+1); - if(spawncycle!=-1) - { - d->o.x = ents[spawncycle].x; - d->o.y = ents[spawncycle].y; - d->o.z = ents[spawncycle].z; - d->yaw = ents[spawncycle].attr1; - d->pitch = 0; - d->roll = 0; - } - else - { - d->o.x = d->o.y = (float)ssize/2; - d->o.z = 4; - }; - entinmap(d); - spawnstate(d); - d->state = CS_ALIVE; - }; - - // movement input code - - #define dir(name,v,d,s,os) void name(bool isdown) { player1->s = isdown; player1->v = isdown ? d : (player1->os ? -(d) : 0); player1->lastmove = lastmillis; }; - - dir(backward, move, -1, k_down, k_up); - dir(forward, move, 1, k_up, k_down); - dir(left, strafe, 1, k_left, k_right); - dir(right, strafe, -1, k_right, k_left); - - void attack(bool on) - { - if(intermission) return; - if(editmode) editdrag(on); - else if(player1->attacking = on) respawn(); - }; - - void jumpn(bool on) { if(!intermission && (player1->jumpnext = on) ) respawn(); }; - - COMMAND(backward, ARG_DOWN); - COMMAND(forward, ARG_DOWN); - COMMAND(left, ARG_DOWN); - COMMAND(right, ARG_DOWN); - COMMANDN(jump, jumpn, ARG_DOWN); - COMMAND(attack, ARG_DOWN); - COMMAND(showscores, ARG_DOWN); - - void fixplayer1range() - { - const float MAXPITCH = 90.0f; - if(player1->pitch>MAXPITCH) player1->pitch = MAXPITCH; - if(player1->pitch<-MAXPITCH) player1->pitch = -MAXPITCH; - while(player1->yaw<0.0f) player1->yaw += 360.0f; - while(player1->yaw>=360.0f) player1->yaw -= 360.0f; - }; - - void mousemove(int dx, int dy) - { - if(player1->state==CS_DEAD || intermission) return; - const float SENSF = 33.0f; // try match quake sens - player1->yaw += (dx/SENSF)*(sensitivity/(float)sensitivityscale); - player1->pitch -= (dy/SENSF)*(sensitivity/(float)sensitivityscale)*(invmouse ? -1 : 1); - fixplayer1range(); - }; - - // damage arriving from the network, monsters, yourself, all ends up here. - - void selfdamage(int damage, int actor, dynent *act) - { - if(player1->state!=CS_ALIVE || editmode || intermission) return; - damageblend(damage); - demoblend(damage); - int ad = damage*30/100;//int ad = damage*(player1->armourtype+1)*20/100; // let armour absorb when possible - if(ad>player1->armour) ad = player1->armour; - player1->armour -= ad; - damage -= ad; - float droll = damage/0.5f; - player1->roll += player1->roll>0 ? droll : (player1->roll<0 ? -droll : (rnd(2) ? droll : -droll)); // give player a kick depending on amount of damage - if((player1->health -= damage)<=0) - { - if(actor==-2) - { - conoutf("you got killed by %s!", (int)&act->name); - } - else if(actor==-1) - { - actor = getclientnum(); - conoutf("you suicided!"); - addmsg(1, 2, SV_FRAGS, --player1->frags); - } - else - { - dynent *a = getclient(actor); - if(a) - { - if(isteam(a->team, player1->team)) - { - conoutf("you got fragged by a teammate (%s)", (int)a->name); - } - else - { - conoutf("you got fragged by %s", (int)a->name); - }; - }; - }; - showscores(true); - addmsg(1, 2, SV_DIED, actor); - player1->lifesequence++; - player1->attacking = false; - player1->state = CS_DEAD; - player1->oldpitch = player1->pitch; - player1->pitch = 0; - player1->roll = 60; - playsound(S_DIE1+rnd(2)); - spawnstate(player1); - player1->lastaction = lastmillis; - } - else - { - playsound(S_PAIN6); - }; +}; + +void timeupdate(int timeremain) +{ + if(!timeremain) + { + intermission = true; + player1->attacking = false; + conoutf("intermission:"); + conoutf("game has ended!"); + showscores(true); + } + else + { + conoutf("time remaining: %d minutes", timeremain); + }; +}; + +dynent *getclient(int cn) // ensure valid entity +{ + if(cn<0 || cn>=MAXCLIENTS) + { + neterr("clientnum"); + return NULL; + }; + while(cn>=players.length()) players.add(NULL); + return players[cn] ? players[cn] : (players[cn] = newdynent()); +}; + +void addc() { strcpy(getclient(1)->team, "CT"); getclient(1)->o = player1->o; strcpy(getclient(1)->name, "sucker"); } COMMAND(addc, ARG_NONE); // FIXME + +void initclient() +{ + clientmap[0] = 0; + initclientnet(); +}; + +void startmap(char *name) // called just after a map load +{ + //if(netmapstart()) { gamemode = 0;}; //needs fixed to switch modes? + netmapstart(); //should work + sleepwait = 0; + //put call to clear/restart game mode extras here + projreset(); + shotlinereset(); + spawncycle = -1; + spawnplayer(player1); + player1->frags = 0; + loopv(players) if(players[i]) players[i]->frags = 0; + resetspawns(); + strcpy_s(clientmap, name); + if(editmode) toggleedit(); + setvar("gamespeed", 100); + setvar("fog", 180); + setvar("fogcolour", 0x8099B3); + showscores(false); + intermission = false; + framesinmap = 0; + conoutf("game mode is %s", (int)modestr(gamemode)); +}; + +COMMANDN(map, changemap, ARG_1STR); + +void suicide() +{ + if (multiplayer()) conoutf("there are others willing to kill you..."); + else conoutf("this is not the answer"); + selfdamage(1000, -1, player1); + //if(d==player1) selfdamage(dm, -1, d); + //else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); playsound(S_FALL1+rnd(5), &d->o); }; + //particle_splash(3, 1000, 1000, player1->o); //edit out? + demodamage(1000, player1->o); + playsound(S_SUICIDE, &player1->o); }; +COMMAND(suicide, ARG_NONE); void killdummies() { loopv(players) if(strcmp(players[i]->name, "dummy") == 0) { players[i]->lastaction = lastmillis; players[i]->health=1; }; }; COMMAND(killdummies, ARG_NONE); - - -void timeupdate(int timeremain) - -{ - - if(!timeremain) - - { - - intermission = true; - - player1->attacking = false; - - conoutf("intermission:"); - - conoutf("game has ended!"); - - showscores(true); - - } - - else - - { - - conoutf("time remaining: %d minutes", timeremain); - - }; - -}; - - - -dynent *getclient(int cn) // ensure valid entity - -{ - - if(cn<0 || cn>=MAXCLIENTS) - - { - - neterr("clientnum"); - - return NULL; - - }; - - while(cn>=players.length()) players.add(NULL); - - return players[cn] ? players[cn] : (players[cn] = newdynent()); - -}; - - - -void addc() { strcpy(getclient(1)->team, "CT"); getclient(1)->o = player1->o; strcpy(getclient(1)->name, "sucker"); } COMMAND(addc, ARG_NONE); // FIXME - - - -void initclient() - -{ - - clientmap[0] = 0; - - initclientnet(); - -}; - - - -void startmap(char *name) // called just after a map load - -{ - - //if(netmapstart()) { gamemode = 0;}; //needs fixed to switch modes? - - netmapstart(); //should work - - sleepwait = 0; - - //put call to clear/restart game mode extras here - - projreset(); - - shotlinereset(); - - spawncycle = -1; - - spawnplayer(player1); - - player1->frags = 0; - - loopv(players) if(players[i]) players[i]->frags = 0; - - resetspawns(); - - strcpy_s(clientmap, name); - - if(editmode) toggleedit(); - - setvar("gamespeed", 100); - - setvar("fog", 180); - - setvar("fogcolour", 0x8099B3); - - showscores(false); - - intermission = false; - - framesinmap = 0; - - conoutf("game mode is %s", (int)modestr(gamemode)); - -}; - - - -COMMANDN(map, changemap, ARG_1STR); - - - -void suicide() - -{ - - if (multiplayer()) conoutf("there are others willing to kill you..."); - - else conoutf("this is not the answer"); - - selfdamage(1000, -1, player1); - - //if(d==player1) selfdamage(dm, -1, d); - - //else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); playsound(S_FALL1+rnd(5), &d->o); }; - - //particle_splash(3, 1000, 1000, player1->o); //edit out? - - demodamage(1000, player1->o); - - playsound(S_SUICIDE, &player1->o); - - - -}; - - - -COMMAND(suicide, ARG_NONE); - diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 443b3951..02880a35 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -333,6 +333,12 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th p += mapsize; changemapserv(text, gamemode); break; + }; + + case SV_WEAPCHANGE: + { + players[cn]->gunselect = getint(p); + break; }; case SV_SERVMSG: diff --git a/source/src/cube.h b/source/src/cube.h index c075076c..7bedc2d3 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -199,7 +199,7 @@ enum SV_MAPCHANGE, SV_ITEMSPAWN, SV_ITEMPICKUP, SV_DENIED, SV_PING, SV_PONG, SV_CLIENTPING, SV_GAMEMODE, SV_EDITH, SV_EDITT, SV_EDITS, SV_EDITD, SV_EDITE, - SV_SENDMAP, SV_RECVMAP, SV_SERVMSG, SV_ITEMLIST, + SV_SENDMAP, SV_RECVMAP, SV_SERVMSG, SV_ITEMLIST, SV_WEAPCHANGE, SV_EXT, }; diff --git a/source/src/protos.h b/source/src/protos.h index 64473745..93c5dd70 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -239,6 +239,7 @@ extern int attackdelay(int gun); extern int magsize(int gun); extern int kick_rot(int gun); extern int kick_back(int gun); +extern bool gun_changed; // entities extern void renderents(); diff --git a/source/src/serverutil.cpp b/source/src/serverutil.cpp index 13a0252b..ed2f2fee 100644 --- a/source/src/serverutil.cpp +++ b/source/src/serverutil.cpp @@ -44,7 +44,7 @@ char msgsizesl[] = // size inclusive message token, 0 for variable SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 3, SV_DENIED, 2, SV_PING, 2, SV_PONG, 2, SV_CLIENTPING, 2, SV_GAMEMODE, 2, SV_EDITH, 7, SV_EDITT, 7, SV_EDITS, 6, SV_EDITD, 6, SV_EDITE, 6, - SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, + SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, SV_WEAPCHANGE, 2, SV_EXT, 0, -1 }; diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 3ae2254c..460bf46b 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -26,6 +26,8 @@ guninfo guns[NUMGUNS] = { S_GRENADE, S_NULL, 1000, 2000, 150, 20, 6, 1, 1, 1, 3, 1, "grenade" }, }; + +bool gun_changed = false; //weapon selection void wup() @@ -37,7 +39,9 @@ void wup() else if(player1->gunselect==player1->primary) player1->gunselect=GUN_KNIFE; - conoutf("%s selected", (int)guns[player1->gunselect].name); + conoutf("%s selected", (int)guns[player1->gunselect].name); + + gun_changed = true; }; void wdw() @@ -49,22 +53,27 @@ void wdw() else if(player1->gunselect==GUN_PISTOL) player1->gunselect=GUN_KNIFE; - conoutf("%s selected", (int)guns[player1->gunselect].name); + conoutf("%s selected", (int)guns[player1->gunselect].name); + + gun_changed = true; }; void primary() { - player1->gunselect=player1->primary; + player1->gunselect=player1->primary; + gun_changed = true; }; void secondary() { - player1->gunselect=GUN_PISTOL; + player1->gunselect=GUN_PISTOL; + gun_changed = true; }; void melee() { - player1->gunselect=GUN_KNIFE; + player1->gunselect=GUN_KNIFE; + gun_changed = true; }; COMMAND(primary,ARG_NONE);