From f31e26c5d3594373e07fd43c83b7aaf055df6783 Mon Sep 17 00:00:00 2001 From: driAn Date: Sun, 14 Aug 2005 17:49:15 +0000 Subject: [PATCH] rollback git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@28 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/Makefile | 20 +- source/src/clientextras.cpp | 6 +- source/src/clientgame.cpp | 1150 +++++++++++++++++------------------ source/src/clients2c.cpp | 243 +------- source/src/cube.h | 167 +---- source/src/editing.cpp | 2 +- source/src/entities.cpp | 530 +++++++--------- source/src/physics.cpp | 694 ++++++++++----------- source/src/protos.h | 33 +- source/src/renderextras.cpp | 13 +- source/src/rendergl.cpp | 10 +- source/src/rendermd2.cpp | 5 +- source/src/savegamedemo.cpp | 33 +- source/src/server.cpp | 247 +------- source/src/serverutil.cpp | 26 +- source/src/sound.cpp | 7 - source/src/weapon.cpp | 347 +---------- source/src/world.cpp | 14 +- source/src/worldio.cpp | 14 +- 19 files changed, 1200 insertions(+), 2361 deletions(-) diff --git a/source/src/Makefile b/source/src/Makefile index fcc8bb07..9dc47028 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -34,21 +34,13 @@ CLIENT_OBJS= \ worldio.o \ worldlight.o \ worldocull.o \ - worldrender.o \ - bot/bot.o \ - bot/botmanager.o \ - bot/bot_ai.o \ - bot/bot_util.o \ - bot/bot_waypoint.o \ - bot/ac_bot.o \ - bot/ac_bot_ai.o - + worldrender.o SERVER_LIBS=-L../enet -lenet SERVER_OBJS= \ standalone.o \ serverms.o \ - servstndalone.o \ + server.o \ tools.o default: all @@ -59,18 +51,14 @@ enet: -make -C ../enet all clean: - -rm -f $(SERVER_OBJS) $(CLIENT_OBJS) + -rm -f $(SERVER_OBJS) $(CLIENT_OBJS) ../../bin/ac_server ../../bin/ac_client -make -C ../enet/ clean - standalone.o: $(CXX) $(CXXFLAGS) -DSTANDALONE -o standalone.o -c serverutil.cpp -servstndalone.o: - $(CXX) $(CXXFLAGS) -DSTANDALONE -o servstndalone.o -c server.cpp - client: $(CLIENT_OBJS) - $(CXX) $(CXXFLAGS) -g -o ../../bin/ac_client $(CLIENT_OBJS) $(CLIENT_LIBS) + $(CXX) $(CXXFLAGS) -o ../../bin/ac_client $(CLIENT_OBJS) $(CLIENT_LIBS) server: $(SERVER_OBJS) $(CXX) $(CXXFLAGS) -o ../../bin/ac_server $(SERVER_OBJS) $(SERVER_LIBS) diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index c570900b..ef13609d 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -37,8 +37,6 @@ void renderclient(dynent *d, bool team, char *mdlname, bool hellpig, float scale else { n = 14; speed = 1200/d->maxspeed*scale; if(hellpig) speed = 300/d->maxspeed; }; if(hellpig) { n++; scale *= 32; mz -= 1.9f; }; rendermodel(mdlname, frame[n], range[n], 0, 1.5f, d->o.x, mz, d->o.y, d->yaw+90, d->pitch/2, team, scale, speed, 0, basetime); - - //rendermd3player(d); }; extern int democlientnum; @@ -47,7 +45,7 @@ void renderclients() { dynent *d; loopv(players) - if((d = players[i]) && (!demoplayback || i!=democlientnum) && players[i] != player1) + if((d = players[i]) && (!demoplayback || i!=democlientnum)) { if (d->state==CS_DEAD) break; //cheap hack fix of @@ -107,14 +105,12 @@ void renderscores() scorelines.setsize(0); if(!demoplayback) renderscore(player1); loopv(players) if(players[i]) renderscore(players[i]); - BotManager.RenderBotScore(); // Added by Rick: Render Score for bots sortmenu(0, scorelines.length()); if(m_teammode) { teamsused = 0; loopv(players) addteamscore(players[i]); if(!demoplayback) addteamscore(player1); - BotManager.AddBotTeamScore(); // Added by Rick: Add team scores for bots teamscores[0] = 0; loopj(teamsused) { diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index 93b9d925..e120eb99 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -1,590 +1,560 @@ -// 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 - -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->armourtype = A_BLUE; - d->quadmillis = 0; - d->gunselect = GUN_PISTOL; - d->gunwait = 0; - d->attacking = false; - d->lastaction = 0; - loopi(NUMGUNS) d->ammo[i] = 0; - d->ammo[GUN_KNIFE] = 1; - //equp with default pistol - d->ammo[GUN_PISTOL] = 24; - d->mag[GUN_PISTOL] = 12; - - /* - 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; - }; - */ - - d->ammo[GUN_SHOTGUN] = 8; - d->mag[GUN_SHOTGUN] = 20; - - // Added by Rick - loopi(MAX_STORED_LOCATIONS) d->PrevLocations.Reset(); - // End add - - //add cases to switch setup default player in different modes here -}; - - -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->altattack = false; - d->nextprimary = 1; - d->nextarmour = false; - // edit: driAn - loopi(3) - { - d->mdl[i] = i; - d->animstate[i].frm = 0; - d->animstate[i].anim = 0; - d->animstate[i].lastTime = 0; - }; - 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; -// FIXME 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); -// FIXME else -// FIXME conoutf("%s is the survior!", (int)lastname); - } - else conoutf("everyone died!"); -// FIXME arenarespawnwait = int health, armour, armourtype, quadmillis;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"); - }; -}; - -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 - }; - - // Added by Rick - if (!ishost()) - { - loopv(bots) - { - if(bots[i] && bots[i]->state != CS_DEAD && (!demoplayback)) - moveplayer(bots[i], 2, false); // use physics to extrapolate bot position - } - } - // End add -}; - -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(); - checkquad(millis); - //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 - }; - otherplayers(); - if(!demoplayback) - { - //monsterthink(); - - // Added by Rick: let bots think - BotManager.Think(); - - //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); - //FIXME 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! -{ - 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*25/100; // let armour absorb when possible armour absorbs 25% - 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) - { - // Added by Rick - if (act->bIsBot && (actor == -2)) - actor = BotManager.GetBotIndex(act); - - 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 - { - // Modified by Rick - //dynent *a = getclient(actor); - dynent *a; - if (act->bIsBot) a = act; - else a = getclient(actor); - // End mod - - 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); Modified by Rick: Notify if the killer was a bot - addmsg(1, 3, SV_DIED, actor, act->bIsBot); - player1->lifesequence++; - player1->attacking = false; - player1->state = CS_DEAD; - player1->pitch = 0; - player1->roll = 60; - if(actor==-1) //suicide - playsound(S_SUICIDE); - else - playsound(S_DIE1+rnd(2)); //add suicide sound - spawnstate(player1); - player1->lastaction = lastmillis; - // Added by Rick: If this player is killed by a bot, update the bots frag count - if (act->bIsBot) - addmsg(1, 3, SV_BOTFRAGS, BotManager.GetBotIndex(act), ++act->frags); - } - 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()); -}; - -// Added by Rick -dynent *getbot(int cn) // ensure valid entity -{ - if(cn<0 || cn>=MAXCLIENTS) - { - neterr("botnum"); - return NULL; - }; - - while(cn>=bots.length()) bots.add(NULL); - if (!bots[cn]) - { - bots[cn] = newdynent(); - if (bots[cn]) - { - bots[cn]->pBot = NULL; - bots[cn]->bIsBot = true; - } - } - - return bots[cn]; -}; -// End add by Rick - -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? - sleepwait = 0; - //monsterclear(); - // Added by Rick - BotManager.BeginMap(name); - // End add by Rick - projreset(); - 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 FOSS( ) -{ - conoutf("Free & Open Source Software owns!"); - player1->maxspeed = 35; -}; -COMMAND( FOSS, ARG_NONE ); +// 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 + +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->armourtype = A_BLUE; + d->quadmillis = 0; + d->gunselect = GUN_PISTOL; + 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 = 3.2f; + 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; + 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 + }; +}; + +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 + }; + 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! +{ + 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*(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->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 initclient() +{ + clientmap[0] = 0; + initclientnet(); +}; + +void startmap(char *name) // called just after a map load +{ + //if(netmapstart()) { gamemode = 0;}; //needs fixed to switch modes? + sleepwait = 0; + //put call to clear/restart game mode extras here + projreset(); + 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 6e6da3b5..d462553d 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -24,29 +24,6 @@ void changemap(char *name) // request map change, server ma strcpy_s(toservermap, name); }; -// Added by Rick -void botcommand(uchar *&p, char *text) -{ - int type = getint(p); - switch(EBotCommands(type)) - { - case COMMAND_ADDBOT: - getint(p); - getint(p); - sgetstr(); - sgetstr(); - break; - case COMMAND_KICKBOT: - if (getint(p)==1) // Kick a specific bot - sgetstr(); - break; - case COMMAND_BOTSKILL: - getint(p); - break; - } -} -// End add - // update the position of other clients in the game in our world // don't care if he's in the scenery or other players, // just don't overlap with our client @@ -179,11 +156,6 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th { c2sinit = false; // send new players my info again conoutf("connected: %s", (int)&text); - // Added by Rick: If we are the host("the bot owner"), tell the bots - // to update their stats - if (ishost()) - BotManager.LetBotsUpdateStats(); - // End add by Rick }; strcpy_s(d->name, text); sgetstr(); @@ -210,12 +182,7 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th e.y = getint(p)/DMF; e.z = getint(p)/DMF; if(gun==GUN_SHOTGUN) createrays(s, e); - // Added by Rick: Check if its a player or bot - int index = getint(p); - dynent *player = (index == -1) ? d : getbot(index); - // shootv(gun, s, e, d); Modified by Rick - shootv(gun, s, e, player); - // End add/mod + shootv(gun, s, e, d); break; }; @@ -224,20 +191,7 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th int target = getint(p); int damage = getint(p); int ls = getint(p); - - // Added by Rick - bool dmgbybot = getint(p); // Damaged by a bot? - int damager = getint(p); // Who is the damager? - // End add - - // Modified by Rick: Check if a bot damaged this player - //if(target==clientnum) { if(ls==player1->lifesequence) selfdamage(damage, cn, d); } - if(target==clientnum) - { - dynent *a = (dmgbybot) ? getbot(damager) : d; - if(ls==player1->lifesequence) - selfdamage(damage, cn, a); - } + if(target==clientnum) { if(ls==player1->lifesequence) selfdamage(damage, cn, d); } else playsound(S_PAIN1+rnd(5), &getclient(target)->o); break; }; @@ -245,15 +199,11 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th case SV_DIED: { int actor = getint(p); - int KilledByBot = getint(p); // Added by Rick - - // if(actor==cn) Modified by Rick - if((actor==cn) && !KilledByBot) + if(actor==cn) { conoutf("%s suicided", (int)d->name); } - // else if(actor==clientnum) Modified by Rick - else if((actor==clientnum) && !KilledByBot) + else if(actor==clientnum) { int frags; if(isteam(player1->team, d->team)) @@ -270,9 +220,7 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th } else { - // dynent *a = getclient(actor); Modifiied by Rick - dynent *a = (KilledByBot) ? getbot(actor) : getclient(actor); - // End mod + dynent *a = getclient(actor); if(a) { if(isteam(a->team, d->name)) @@ -297,7 +245,6 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th case SV_ITEMPICKUP: setspawn(getint(p), false); getint(p); - getint(p); // Added by Rick break; case SV_ITEMSPAWN: @@ -396,186 +343,6 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th for(int n = getint(p); n; n--) getint(p); break; }; - - // Added by Rick: Bot specific messages - case SV_BOTSOUND: - { - int Sound = getint(p); - dynent *pBot = getbot(getint(p)); - - if (pBot) - playsound(Sound, &pBot->o); - - break; - } - - case SV_ADDBOT: // Bot joined the game - { - dynent *b = getbot(getint(p)); - if (!b) break; - - sgetstr(); - if(b->name[0]) // already connected - { - if(strcmp(b->name, text)) - conoutf("%s is now known as %s", (int)b->name, (int)&text); - } - else // new client - { - //c2sinit = false; // send new players my info again - conoutf("connected: %s", (int)&text); - }; - strcpy_s(b->name, text); - sgetstr(); - strcpy_s(b->team, text); - b->lifesequence = getint(p); - b->bIsBot = true; - b->pBot = NULL; - break; - }; - - case SV_BOTDIS: - { - int n = getint(p); - dynent *b = getbot(n); - - if (!b) - break; - - conoutf("bot %s disconnected", (int)(b->name[0] ? b->name : "[incompatible client]")); - delete b->pBot; - zapdynent(bots[n]); - bots.remove(n); - break; - } - - case SV_CLIENT2BOTDMG: - case SV_BOT2BOTDMG: - { - int target = getint(p); - int damage = getint(p); - int damager = getint(p); - dynent *b = getbot(target); - - dynent *a; - if (damager == -1) - { - // HACK! if the local client who sended the message is the damager, its -1 - a = d; - } - else if (type == SV_CLIENT2BOTDMG) - { - if (damager == clientnum) a = player1; - else a = getclient(damager); - } - else - a = getbot(damager); - - if (b && a) - { - // Do we know the bot info? if so we are the host... - if (b->pBot) b->pBot->BotPain(damage, a); - playsound(S_PAIN1+rnd(5), &b->o); - } - break; - } - - case SV_BOTDIED: - { - int b = getint(p); - int killer = getint(p); - bool KilledByABot = getint(p); - dynent *bot = getbot(b); - - if((b==killer) && KilledByABot) - { - conoutf("%s suicided", (int)bot->name); - } - else if((killer==clientnum) && !KilledByABot) - { - int frags; - if(isteam(player1->team, bot->team)) - { - frags = -1; - conoutf("you fragged a teammate (%s)", (int)bot->name); - } - else - { - frags = 1; - conoutf("you fragged %s", (int)bot->name); - }; - addmsg(1, 2, SV_FRAGS, player1->frags += frags); - } - else - { - dynent *k; - if (KilledByABot) - k = getbot(killer); - else if (killer == -1) - // if killer = -1, 'a player1' sended the message(hack) - k = d; - else - k = getclient(killer); - - if(bot && k) - { - if(isteam(bot->team, k->name)) - { - conoutf("%s fragged his teammate (%s)", (int)bot->name, (int)k->name); - } - else - { - conoutf("%s fragged %s", (int)bot->name, (int)k->name); - } - } - } - - playsound(S_DIE1+rnd(2), &bot->o); - bot->lifesequence++; - break; - }; - - case SV_BOTFRAGS: - { - dynent *b = getbot(getint(p)); - if (b) b->frags = getint(p); - break; - } - - case SV_BOTUPDATE: - { - int n = getint(p); - dynent *b = getbot(n); - if(!b) return; - b->o.x = getint(p)/DMF; - b->o.y = getint(p)/DMF; - b->o.z = getint(p)/DMF; - b->yaw = getint(p)/DAF; - b->pitch = getint(p)/DAF; - b->roll = getint(p)/DAF; - b->vel.x = getint(p)/DVF; - b->vel.y = getint(p)/DVF; - b->vel.z = getint(p)/DVF; - int f = getint(p); - b->strafe = (f&3)==3 ? -1 : f&3; - f >>= 2; - b->move = (f&3)==3 ? -1 : f&3; - b->onfloor = (f>>2)&1; - int state = f>>3; - if(state==CS_DEAD && b->state!=CS_DEAD) b->lastaction = lastmillis; - b->state = state; - - if (!b->bIsBot) - b->bIsBot = true; - - if(!demoplayback) updatepos(b); - break; - } - case SV_BOTCOMMAND: - botcommand(p, text); - break; - - // End add default: neterr("type"); diff --git a/source/src/cube.h b/source/src/cube.h index 74c0ce9d..d996666f 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -35,31 +35,16 @@ enum // hardcoded texture numbers DEFAULT_CEIL }; -//FIXME enum // static entity types { NOTUSED = 0, // entity slot not in use in map LIGHT, // lightsource, attr1 = radius, attr2 = intensity PLAYERSTART, // attr1 = angle - I_AMMO, I_PISTOL, I_GRENADE, + I_SHOTGUN, I_SUBGUN, I_SNIPER, I_ASSULT, I_GRENADE, I_PISTOL, I_HEALTH, I_ARMOUR, I_QUAD, MAPMODEL, // attr1 = angle, attr2 = idx CARROT, // attr1 = tag, attr2 = type LADDER, - OBJ_ITEM, - MONSTER, - TRIGGER, - OBJ_SITE, - I_AUTOPISTOL, - I_SHOTGUN, - I_SNIPER, - I_SUBGUN, - I_CARBINE, - I_SEMIRIFLE, - I_AUTORIFLE, - I_HELMET, - A_YELLOW, - I_SEMIPISTOL, MAXENTTYPES }; @@ -105,79 +90,7 @@ struct vec { float x, y, z; }; struct block { int x, y, xs, ys; }; struct mapmodelinfo { int rad, h, zoff, snap; char *name; }; -enum { GUN_KNIFE = 0, GUN_PISTOL, GUN_SEMIPISTOL, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIPER, GUN_ASSULT, GUN_GRENADE, NUMGUNS }; - -enum { MDL_LOWER, MDL_UPPER, MDL_HEAD, MDL_WEAPON }; - -// Added by Rick -class CBot; - -#define MAX_STORED_LOCATIONS 7 - -extern int lastmillis; // last time (Moved up by Rick) - -class CPrevLocation -{ - int nextupdate; - -public: - vec prevloc[MAX_STORED_LOCATIONS]; - - CPrevLocation(void) : nextupdate(0) { Reset(); }; - void Reset(void) { loopi(MAX_STORED_LOCATIONS) prevloc[i].x=prevloc[i].y=prevloc[i].z=0.0f; }; - void Update(const vec &o) - { - extern float GetDistance(vec v1, vec v2); - - if (nextupdate > lastmillis) return; - if (GetDistance(o, prevloc[0]) >= 4.0f) - { - for(int i=(MAX_STORED_LOCATIONS-1);i>=1;i--) - prevloc[i] = prevloc[i-1]; - prevloc[0] = o; - } - nextupdate = lastmillis + 100; - }; -}; - -struct itemstat { int add, max, sound; }; -// End add - -struct md3state -{ - int anim; - int frm; - int lastTime; -}; - -enum // md3 animations -{ - BOTH_DEATH1 = 0, - BOTH_DEAD1, - BOTH_DEATH2, - BOTH_DEAD2, - BOTH_DEATH3, - BOTH_DEAD3, - TORSO_GESTURE, - TORSO_ATTACK, - TORSO_ATTACK2, - TORSO_DROP, - TORSO_RAISE, - TORSO_STAND, - TORSO_STAND2, - LEGS_WALKCR, - LEGS_WALK, - LEGS_RUN, - LEGS_BACK, - LEGS_SWIM, - LEGS_JUMP, - LEGS_LAND, - LEGS_JUMPB, - LEGS_LANDB, - LEGS_IDLE, - LEGS_IDLECR, - LEGS_TURN -}; +enum { GUN_KNIFE = 0, GUN_PISTOL, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIPER, GUN_ASSULT, GUN_GRENADE, NUMGUNS }; struct dynent // players & monsters { @@ -195,7 +108,7 @@ struct dynent // players & monsters int lifesequence; // sequence id for each respawn, used in damage test int state; // one of CS_* below int frags; - int health, armour, quadmillis, armourtype; //removed armour type + int health, armour, armourtype, quadmillis; int gunselect, gunwait; int lastaction, lastattackgun, lastmove; bool attacking; @@ -204,13 +117,10 @@ struct dynent // players & monsters int monsterstate; // one of M_* below, M_NONE means human int mtype; // see monster.cpp dynent *enemy; // monster wants to kill this entity - // Added by Rick: targetpitch - float targetpitch; // monster wants to look in this direction - // End add float targetyaw; // monster wants to look in this direction bool blocked, moving; // used by physics to signal ai int trigger; // millis at which transition to another monsterstate takes place -// vec attacktarget; // delayed attacks + vec attacktarget; // delayed attacks int anger; // how many times already hit by fellow monster string name, team; int startheight; @@ -218,33 +128,11 @@ struct dynent // players & monsters bool reloading; int primary; //primary gun int nextprimary; - bool altattack; - bool hasarmour; - bool nextarmour; - bool playerblocked; - bool onladder; - int mdl[3]; // which models - md3state animstate[3]; // which animations - // Added by Rick - CBot *pBot; // Only used if this is a bot, points to the bot class if we are the host, - // for other clients its NULL - bool bIsBot; // Is this dynent a bot? - CPrevLocation PrevLocations; // Previous stored locations of this player - // End add by Rick }; -// Moved from server.cpp by Rick -struct server_entity // server side version of "entity" type -{ - bool spawned; - int spawnsecs; -}; -// End move - - #define SAVEGAMEVERSION 6 // bump if dynent/netprotocol changes or any other savegame/demo data bumped from 5 -//enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off +enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off enum { M_NONE = 0, M_SEARCH, M_HOME, M_ATTACKING, M_PAIN, M_SLEEP, M_AIMING }; // monster states #define MAXCLIENTS 256 // in a multiplayer game, can be arbitrarily changed @@ -263,10 +151,6 @@ enum 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, - // Added by Rick: Bot specific messages - SV_BOTSOUND, SV_BOTDIS, SV_BOTDIED, SV_CLIENT2BOTDMG, SV_BOT2BOTDMG, - SV_BOTFRAGS, SV_ADDBOT, SV_BOTUPDATE, SV_BOTCOMMAND, - // End add SV_EXT, }; @@ -292,14 +176,6 @@ enum S_FLAUNCH, S_FEXPLODE, S_SPLASH1, S_SPLASH2, S_GRUNT1, S_GRUNT2, S_RUMBLE, - S_PAINO, - S_PAINR, S_DEATHR, - S_PAINE, S_DEATHE, - S_PAINS, S_DEATHS, - S_PAINB, S_DEATHB, - S_PAINP, S_PIGGR2, - S_PAINH, S_DEATHH, - S_PAIND, S_DEATHD, S_NULL }; @@ -322,7 +198,7 @@ extern dvector players; // all the other clients (in multiplayer extern bool editmode; extern vector ents; // map entities extern vec worldpos; // current target of the crosshair in the world -//extern int lastmillis; // last time (Moved up by Rick) +extern int lastmillis; // last time extern int curtime; // current frame time extern int gamemode, nextmode; extern int xtraverts; @@ -350,9 +226,6 @@ extern bool demoplayback; #define vdist(d,v,e,s) vec v = s; vsub(v,e); float d = (float)sqrt(dotprod(v,v)); #define vreject(v,u,max) ((v).x>(u).x+(max) || (v).x<(u).x-(max) || (v).y>(u).y+(max) || (v).y<(u).y-(max)) #define vlinterp(v,f,u,g) { (v).x = (v).x*f+(u).x*g; (v).y = (v).y*f+(u).y*g; (v).z = (v).z*f+(u).z*g; } -// Added by Rick (compares 2 vectors) -#define vis(v1,v2) ((v1.x==v2.x) && (v1.y==v2.y) && (v1.z==v2.z)) -// End add by Rick #define sgetstr() { char *t = text; do { *t = getint(p); } while(*t++); } // used by networking @@ -363,19 +236,17 @@ extern bool demoplayback; 3 - survivor 4 - team survior 5 - ctf -6 - pistols only */ -#define m_noitems (gamemode==3 || gamemode==4 || gamemode==6) -#define m_noitemsrail (false) //dunno what this does -#define m_pistols (gamemode==6) +#define m_noitems (false) +#define m_noitemsrail (false) #define m_arena (gamemode==3 || gamemode==4) #define m_tarena (gamemode==4) -#define m_teammode (gamemode==0 || (gamemode>=4 & !m_pistols)) +#define m_teammode (gamemode==0 || gamemode>=4) #define m_ctf (gamemode==5) -#define m_sp (gamemode<0) -#define m_dmsp (gamemode==-1) -#define m_classicsp (gamemode==-2) +//#define m_sp (gamemode<0) +//#define m_dmsp (gamemode==-1) +//#define m_classicsp (gamemode==-2) #define isteam(a,b) (m_teammode && strcmp(a, b)==0) enum // function signatures for script functions, see command.cpp @@ -419,19 +290,5 @@ enum // function signatures for script functions, see command.cpp #include -// Added by Rick -extern ENetHost *clienthost; -inline bool ishost(void) { return !clienthost; }; - -void splaysound(int n, vec *loc=0); -void addteamscore(dynent *d); -void renderscore(dynent *d); -extern void conoutf(const char *s, int a = 0, int b = 0, int c = 0); // Moved from protos.h -extern void particle_trail(int type, int fade, vec &from, vec &to); // Moved from protos.h -extern bool listenserv; -extern bool intermission; -#include "bot/bot.h" -// End add by Rick - #include "protos.h" // external function decls diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 2a1c4a5c..4df636b7 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -44,7 +44,7 @@ void toggleedit() else { resettagareas(); // clear trigger areas to allow them to be edited - player1->health = 100; + player1->health = 100; //put call to clear/restar gamemode projreset(); }; diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 39d1d256..03314829 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -1,310 +1,220 @@ -// entities.cpp: map entity related functions (pickup etc.) - -#include "cube.h" - -vector ents; - -//fill in 2nd rrounds wth grenade, 3rd with plasma -char *entmdlnames[] = -{ - "shells", "bullets", "rockets", "rrounds", "rrounds", "rrounds", "health", "armour", "quad", -}; - -int triggertime = 0; - -void renderent(entity &e, char *mdlname, float z, float yaw, int frame = 0, int numf = 1, int basetime = 0, float speed = 10.0f) -{ - rendermodel(mdlname, frame, numf, 0, 1.1f, e.x, z+S(e.x, e.y)->floor, e.y, yaw, 0, false, 1.0f, speed, 0, basetime); -}; - -void renderentities() -{ - if(lastmillis>triggertime+1000) triggertime = 0; - loopv(ents) - { - entity &e = ents[i]; - if(e.type==MAPMODEL) - { - mapmodelinfo &mmi = getmminfo(e.attr2); - if(!&mmi) continue; - rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, e.x, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, false, 1.0f, 10.0f, mmi.snap); - } - else - { - if(OUTBORD(e.x, e.y)) continue; - if(e.type!=CARROT) - { - if(!e.spawned) continue; - if(e.typeI_QUAD) continue; - renderent(e, entmdlnames[e.type-I_AMMO], (float)(1+sin(lastmillis/100.0+e.x+e.y)/20), lastmillis/10.0f); - } - else switch(e.attr2) - { - case 1: - case 3: - continue; - - case 2: - case 0: - if(!e.spawned) continue; - renderent(e, "carrot", (float)(1+sin(lastmillis/100.0+e.x+e.y)/20), lastmillis/(e.attr2 ? 1.0f : 10.0f)); - break; - - case 4: renderent(e, "switch2", 3, (float)e.attr3*90, (!e.spawned && !triggertime) ? 1 : 0, (e.spawned || !triggertime) ? 1 : 2, triggertime, 1050.0f); break; - case 5: renderent(e, "switch1", -0.15f, (float)e.attr3*90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; - }; - }; - }; -}; - -//edit these items -// struct itemstat { int add, max, sound; } itemstats[] = Modified by Rick -itemstat itemstats[] = -{ - 10, 50, S_ITEMAMMO, //semipistol - 20, 100, S_ITEMAMMO, //autopistol - 5, 25, S_ITEMAMMO, //shotgun - 5, 25, S_ITEMAMMO, //sniper - 25, 100, S_ITEMAMMO, //subgun - 50, 200, S_ITEMAMMO, //carbine - 100, 100, S_ITEMAMMO, //semigun - 150, 150, S_ITEMAMMO, //autorifle - 1, 1, S_ITEMAMMO, //grenade - 150, 150, S_ITEMARMOUR, //helmet - 100, 100, S_ITEMARMOUR, //armour - 20000, 30000, S_ITEMPUP, //bomb - - -}; - -void baseammo(int gun) { player1->ammo[gun] = itemstats[gun-1].add*2; }; - -// Added by Rick: baseammo for bots -void botbaseammo(int gun, dynent *d) { d->ammo[gun] = itemstats[gun-1].add*2; }; -// End add - -// these two functions are called when the server acknowledges that you really -// picked up the item (in multiplayer someone may grab it before you). - -void radditem(int i, int &v) -{ - itemstat &is = itemstats[ents[i].type-I_AMMO]; - ents[i].spawned = false; - v += is.add; - if(v>is.max) v = is.max; - playsoundc(is.sound); -}; - -void realpickup(int n, dynent *d) -{ - switch(ents[n].type) - { -/* case I_PISTOL: radditem(n, d->ammo[1]); break; - - case I_AMMO: radditem(n, d->ammo[2]); break; - case I_SUBGUN: radditem(n, d->ammo[3]); break; - case I_SNIPER: radditem(n, d->ammo[4]); break; - case I_ASSAULT: radditem(n, d->ammo[5]); break; - case I_GRENADE: radditem(n, d->ammo[6]); break; -*/ - case I_HEALTH: radditem(n, d->health); break; - - case I_ARMOUR: - radditem(n, d->armour); - d->hasarmour = true; - break; - - case I_QUAD: - radditem(n, d->quadmillis); - conoutf("you got the quad!"); - break; - }; -}; - -// these functions are called when the client touches the item - -void additem(int i, int &v, int spawnsec) -{ - if(v4 ? 2 : 3); // spawn times are dependent on number of players - int ammo = np*2; - switch(ents[n].type) - { -/* - case I_PISTOL: additem(n, d->ammo[1], ammo); break; - - case I_AMMO: additem(n, d->ammo[2], ammo); break; - case I_SUBGUN: additem(n, d->ammo[3], ammo); break; - case I_SNIPER: additem(n, d->ammo[4], ammo); break; - case I_ASSAULT: additem(n, d->ammo[5], ammo); break; - case I_GRENADE: additem(n, d->ammo[6], ammo); break; -*/ - case I_HEALTH: additem(n, d->health, np*5); break; - - case I_ARMOUR: - additem(n, d->armour, 20); - break; - - case I_QUAD: - additem(n, d->quadmillis, 60); - break; - - case CARROT: - ents[n].spawned = false; - triggertime = lastmillis; - trigger(ents[n].attr1, ents[n].attr2, false); // needs to go over server for multiplayer - break; - - case OBJ_ITEM: - additem(n, d->quadmillis, 60); - break; - - case TRIGGER: - ents[n].spawned = false; - triggertime = lastmillis; - trigger(ents[n].attr1, ents[n].attr2, false); // needs to go over server for multiplayer - BotManager.PickNextTrigger(); // Added by Rick - break; - - }; -}; - -void checkitems() -{ - if(editmode) return; - loopv(ents) - { - entity &e = ents[i]; - if(e.type==NOTUSED) continue; - if(!ents[i].spawned) continue; - if(OUTBORD(e.x, e.y)) continue; - vec v = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; - vdist(dist, t, player1->o, v); - if(dist<2.5) pickup(i, player1); - }; -}; - -void putitems(uchar *&p) // puts items in network stream and also spawns them locally -{ - loopv(ents) if((ents[i].type>=I_AMMO && ents[i].type<=I_QUAD) || ents[i].type==TRIGGER) - { - putint(p, i); - ents[i].spawned = true; - }; -}; - -void resetspawns() { loopv(ents) ents[i].spawned = false; }; -void setspawn(int i, bool on) { if(inextprimary!=i) d->ammo[i] = 0; - d->mag[GUN_KNIFE] = 1; - - d->mag[GUN_PISTOL] = 8; - d->ammo[GUN_PISTOL] = 24; - - if(m_pistols) - { - d->primary=GUN_PISTOL; - d->ammo[GUN_PISTOL] = 48; //change? - return; - }; - - if (d->primary==GUN_PISTOL) // || pistol only mode! - { - d->ammo[d->primary] = 48; - } - else if (d->primary>GUN_PISTOL && d->primaryammo[d->primary] = itemstats[d->primary-2].max; - d->mag[d->primary] = itemstats[d->primary-2].add; - } - else if (d->primary==GUN_GRENADE) - { - conoutf("you don't have to worry about blowing your hand off just yet..."); - } - - /* - if (d->armour) - { - d->armour = 100; - } - */ - //if(m_noitems) { conoutf("i am (not) sorry, but an armour choice is only for ts and lms"); return; }; - - if(d->nextarmour==true) - { - if(!m_noitems) return;{ conoutf("armour is only for ts and lms modes, maybe you can hide"); return; }; - d->hasarmour = true; - d->armour=itemstats[7].add; - } - else - { - d->hasarmour = false; - }; -}; - -void add(int num) -{ - if (num>0 && num<6) player1->nextprimary = num; - else - { - if (num==7 && m_noitems) player1->nextarmour=!player1->nextarmour; - else conoutf("armour is only for ts and lms modes, maybe you can hide"); - }; -}; - -COMMAND(add,ARG_1INT); - -// Added by Rick -bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entity bounding box(entity version) -{ - mapmodelinfo &mmi = getmminfo(e->attr2); - if(!&mmi || !mmi.h) return false; - - float lo = (float)(S(e->x, e->y)->floor+mmi.zoff+e->attr3); - float hi = lo+mmi.h; - vec v = to, w = { e->x, e->y, lo + (fabs(hi-lo)/2.0f) }, *p; - vsub(v, from); - vsub(w, from); - float c1 = dotprod(w, v); - - if(c1<=0) p = &from; - else - { - float c2 = dotprod(v, v); - if(c2<=c1) p = &to; - else - { - float f = c1/c2; - vmul(v, f); - vadd(v, from); - p = &v; - }; - }; - - if (p->x <= e->x+mmi.rad - && p->x >= e->x-mmi.rad - && p->y <= e->y+mmi.rad - && p->y >= e->y-mmi.rad - && p->z <= hi - && p->z >= lo) - { - if (end) *end = *p; - return true; - } - return false; -}; -// End add by Ricks +// entities.cpp: map entity related functions (pickup etc.) + +#include "cube.h" + +vector ents; + +//fill in 2nd rrounds wth grenade, 3rd with plasma +char *entmdlnames[] = +{ + "shells", "bullets", "rockets", "rrounds", "rrounds", "rrounds", "health", "armour", "quad", +}; + +int triggertime = 0; + +void renderent(entity &e, char *mdlname, float z, float yaw, int frame = 0, int numf = 1, int basetime = 0, float speed = 10.0f) +{ + rendermodel(mdlname, frame, numf, 0, 1.1f, e.x, z+S(e.x, e.y)->floor, e.y, yaw, 0, false, 1.0f, speed, 0, basetime); +}; + +void renderentities() +{ + if(lastmillis>triggertime+1000) triggertime = 0; + loopv(ents) + { + entity &e = ents[i]; + if(e.type==MAPMODEL) + { + mapmodelinfo &mmi = getmminfo(e.attr2); + if(!&mmi) continue; + rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, e.x, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, false, 1.0f, 10.0f, mmi.snap); + } + else + { + if(OUTBORD(e.x, e.y)) continue; + if(e.type!=CARROT) + { + if(!e.spawned) continue; + if(e.typeI_QUAD) continue; + renderent(e, entmdlnames[e.type-I_SHOTGUN], (float)(1+sin(lastmillis/100.0+e.x+e.y)/20), lastmillis/10.0f); + } + else switch(e.attr2) + { + case 1: + case 3: + continue; + + case 2: + case 0: + if(!e.spawned) continue; + renderent(e, "carrot", (float)(1+sin(lastmillis/100.0+e.x+e.y)/20), lastmillis/(e.attr2 ? 1.0f : 10.0f)); + break; + + case 4: renderent(e, "switch2", 3, (float)e.attr3*90, (!e.spawned && !triggertime) ? 1 : 0, (e.spawned || !triggertime) ? 1 : 2, triggertime, 1050.0f); break; + case 5: renderent(e, "switch1", -0.15f, (float)e.attr3*90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; + }; + }; + }; +}; + +struct itemstat { int add, max, sound; } itemstats[] = +{ + 7, 14, S_ITEMAMMO, //shotgun + 30, 90, S_ITEMAMMO, //subgun + 5, 15, S_ITEMAMMO, //sniper + 20, 40, S_ITEMAMMO, //assult + 1, 2, S_ITEMAMMO, //grenade + 5, 10, S_ITEMAMMO, //pistol + 25, 100, S_ITEMHEALTH, //health + 100, 150, S_ITEMARMOUR, //armour + 20000, 30000, S_ITEMPUP, //powerup +}; + +void baseammo(int gun) { player1->ammo[gun] = itemstats[gun-1].add*2; }; + +// these two functions are called when the server acknowledges that you really +// picked up the item (in multiplayer someone may grab it before you). + +void radditem(int i, int &v) +{ + itemstat &is = itemstats[ents[i].type-I_SHOTGUN]; + ents[i].spawned = false; + v += is.add; + if(v>is.max) v = is.max; + playsoundc(is.sound); +}; + +void realpickup(int n, dynent *d) +{ + switch(ents[n].type) + { + case I_PISTOL: radditem(n, d->ammo[1]); break; + case I_SHOTGUN: radditem(n, d->ammo[2]); break; + case I_SUBGUN: radditem(n, d->ammo[3]); break; + case I_SNIPER: radditem(n, d->ammo[4]); break; + case I_ASSULT: radditem(n, d->ammo[5]); break; + case I_GRENADE: radditem(n, d->ammo[6]); break; + case I_HEALTH: radditem(n, d->health); break; + + case I_ARMOUR: + radditem(n, d->armour); + d->armourtype = A_YELLOW; + break; + + case I_QUAD: + radditem(n, d->quadmillis); + conoutf("you got the quad!"); + break; + }; +}; + +// these functions are called when the client touches the item + +void additem(int i, int &v, int spawnsec) +{ + if(v4 ? 2 : 3); // spawn times are dependent on number of players + int ammo = np*2; + switch(ents[n].type) + { + case I_PISTOL: additem(n, d->ammo[1], ammo); break; + case I_SHOTGUN: additem(n, d->ammo[2], ammo); break; + case I_SUBGUN: additem(n, d->ammo[3], ammo); break; + case I_SNIPER: additem(n, d->ammo[4], ammo); break; + case I_ASSULT: additem(n, d->ammo[5], ammo); break; + case I_GRENADE: additem(n, d->ammo[6], ammo); break; + case I_HEALTH: additem(n, d->health, np*5); break; + + case I_ARMOUR: + additem(n, d->armour, 20); + break; + + case I_QUAD: + additem(n, d->quadmillis, 60); + break; + + case CARROT: + ents[n].spawned = false; + triggertime = lastmillis; + trigger(ents[n].attr1, ents[n].attr2, false); // needs to go over server for multiplayer + break; + + }; +}; + +void checkitems() +{ + if(editmode) return; + loopv(ents) + { + entity &e = ents[i]; + if(e.type==NOTUSED) continue; + if(!ents[i].spawned) continue; + if(OUTBORD(e.x, e.y)) continue; + vec v = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; + vdist(dist, t, player1->o, v); + if(dist<2.5) pickup(i, player1); + }; +}; + +void putitems(uchar *&p) // puts items in network stream and also spawns them locally +{ + loopv(ents) if((ents[i].type>=I_SHOTGUN && ents[i].type<=I_QUAD) || ents[i].type==CARROT) + { + putint(p, i); + ents[i].spawned = true; + }; +}; + +void resetspawns() { loopv(ents) ents[i].spawned = false; }; +void setspawn(int i, bool on) { if(inextprimary!=i) d->ammo[i] = 0; + d->mag[GUN_KNIFE] = 1; + + d->mag[GUN_PISTOL] = 8; + d->ammo[GUN_PISTOL] = 24; + + if (d->primary==GUN_PISTOL) // || pistol only mode! + { + d->ammo[d->primary] = 48; + } + else if (d->primary>GUN_PISTOL && d->primaryammo[d->primary] = itemstats[d->primary-2].max; + d->mag[d->primary] = itemstats[d->primary-2].add; + } + else if (d->primary==GUN_GRENADE) + { + conoutf("you don't have to worry about blowing your hand off just yet..."); + } + + /* + if (d->armour) + { + d->armour = 100; + } + */ +}; + +void add(int num) +{ + + + if (num>0 && num<8) player1->nextprimary = num; +}; + +COMMAND(add,ARG_1INT); \ No newline at end of file diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 59ca58df..703dbb13 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -1,356 +1,338 @@ -// physics.cpp: no physics books were hurt nor consulted in the construction of this code. -// All physics computations and constants were invented on the fly and simply tweaked until -// they "felt right", and have no basis in reality. Collision detection is simplistic but -// very robust (uses discrete steps at fixed fps). - -#include "cube.h" - -/* Modified by Rick: Fix, so we can jump on players aswell -bool plcollide(dynent *d, dynent *o, float &headspace) // collide with player or monster -{ - if(o->state!=CS_ALIVE) return true; - const float r = o->radius+d->radius; - if(fabs(o->o.x-d->o.x)o.y-d->o.y)o.z-d->o.z)aboveeye+d->eyeheight) return false; - if(d->monsterstate) return false; // hack - headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; - if(headspace<0) headspace = 10; - }; - return true; -}; -*/ - -bool plcollide(dynent *d, dynent *o, float &headspace, float &hi, float &lo) // collide with player or monster -{ - if(o->state!=CS_ALIVE) return true; - const float r = o->radius+d->radius; - if(fabs(o->o.x-d->o.x)o.y-d->o.y)o.z-d->eyeheighto.z-o->eyeheight) { if(o->o.z-o->eyeheighto.z-o->eyeheight-1; } - else if(o->o.z+o->aboveeye>lo) lo = o->o.z+o->aboveeye+1; - - if(fabs(o->o.z-d->o.z)aboveeye+d->eyeheight) return false; - //if(d->monsterstate) return false; // hack - headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; - if(headspace<0) headspace = 10; - }; - return true; -}; - -bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs) // recursively collide with a mipmapped corner cube -{ - sqr *w = wmip[mip]; - int sz = ssize>>mip; - bool stest = SOLID(SWS(w, x+dx, y, sz)) && SOLID(SWS(w, x, y+dy, sz)); - mip++; - x /= 2; - y /= 2; - if(SWS(wmip[mip], x, y, ssize>>mip)->type==CORNER) - { - bx = x<radius; - if(fabs(e.x-d->o.x)o.y)floor+mmi.zoff+e.attr3); - if(d->o.z-d->eyeheightlo) lo = mmz+mmi.h; - }; - }; -}; - -// all collision happens here -// spawn is a dirty side effect used in spawning -// drop & rise are supplied by the physics below to indicate gravity/push for current mini-timestep - -bool collide(dynent *d, bool spawn, float drop, float rise) -{ - const float fx1 = d->o.x-d->radius; // figure out integer cube rectangle this entity covers in map - const float fy1 = d->o.y-d->radius; - const float fx2 = d->o.x+d->radius; - const float fy2 = d->o.y+d->radius; - const int x1 = fast_f2nat(fx1); - const int y1 = fast_f2nat(fy1); - const int x2 = fast_f2nat(fx2); - const int y2 = fast_f2nat(fy2); - float hi = 127, lo = -128; - float minfloor = (d->monsterstate && !spawn && d->health>100) ? d->o.z-d->eyeheight-4.5f : -1000.0f; // big monsters are afraid of heights, unless angry :) - - for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map - { - if(OUTBORD(x,y)) return false; - sqr *s = S(x,y); - float ceil = s->ceil; - float floor = s->floor; - switch(s->type) - { - case SOLID: - return false; - - case CORNER: - { - int bx = x, by = y, bs = 1; - if(x==x1 && y==y1 && cornertest(0, x, y, -1, -1, bx, by, bs) && fx1-bx+fy1-by<=bs - || x==x2 && y==y1 && cornertest(0, x, y, 1, -1, bx, by, bs) && fx2-bx>=fy1-by - || x==x1 && y==y2 && cornertest(0, x, y, -1, 1, bx, by, bs) && fx1-bx<=fy2-by - || x==x2 && y==y2 && cornertest(0, x, y, 1, 1, bx, by, bs) && fx2-bx+fy2-by>=bs) - return false; - break; - }; - - case FHF: // FIXME: too simplistic collision with slopes, makes it feels like tiny stairs - floor -= (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; - break; - - case CHF: - ceil += (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; - - }; - if(ceillo) lo = floor; - if(flooreyeheight+d->aboveeye) return false; - - // Modified by Rick: plcollide now takes hi and lo in account aswell, that way we can jump/walk on players - - float headspace = 10; - loopv(players) // collide with other players - { - dynent *o = players[i]; - if(!o || o==d) continue; - if(!plcollide(d, o, headspace, hi, lo)) return false; - }; - - loopv(bots) // Added by Rick: collide with other bots - { - dynent *o = bots[i]; - if(!o || o==d) continue; - if(!plcollide(d, o, headspace, hi, lo)) return false; - }; - - if(d!=player1) if(!plcollide(d, player1, headspace, hi, lo)) return false; - //dvector &v = getmonsters(); - // this loop can be a performance bottleneck with many monster on a slow cpu, - // should replace with a blockmap but seems mostly fast enough - // Modified by Rick: Added v[i] pointer check - //loopv(v) if(v[i] && !vreject(d->o, v[i]->o, 7.0f) && d!=v[i] && !plcollide(d, v[i], headspace, hi, lo)) return false; - headspace -= 0.01f; - - mmcollide(d, hi, lo); // collide with map models - - if(spawn) - { - d->o.z = lo+d->eyeheight; // just drop to floor (sideeffect) - d->onfloor = true; - } - else - { - const float space = d->o.z-d->eyeheight-lo; - if(space<0) - { - if(space>-0.01) d->o.z = lo+d->eyeheight; // stick on step - else if(space>-1.26f) d->o.z += rise; // rise thru stair - else return false; - } - else - { - d->o.z -= min(min(drop, space), headspace); // gravity - }; - - const float space2 = hi-(d->o.z+d->aboveeye); - if(space2<0) - { - if(space2<-0.1) return false; // hack alert! - d->o.z = hi-d->aboveeye; // glue to ceiling - d->vel.z = 0; // cancel out jumping velocity - }; - - d->onfloor = d->o.z-d->eyeheight-lo<0.01f; - }; - return true; -} - -float rad(float x) { return x*3.14159f/180; }; - -VAR(maxroll, 0, 3, 20); - -int physicsfraction = 0, physicsrepeat = 0; -const int MINFRAMETIME = 20; // physics always simulated at 50fps or better - -void physicsframe() // optimally schedule physics frames inside the graphics frames -{ - if(curtime>=MINFRAMETIME) - { - int faketime = curtime+physicsfraction; - physicsrepeat = faketime/MINFRAMETIME; - physicsfraction = faketime-physicsrepeat*MINFRAMETIME; - } - else - { - physicsrepeat = 1; - }; -}; - -// main physics routine, moves a player/monster for a curtime step -// moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) -// local is false for multiplayer prediction - -void moveplayer(dynent *pl, int moveres, bool local, int curtime) -{ - const bool water = hdr.waterlevel>pl->o.z-0.5f; - const bool floating = (editmode && local) || pl->state==CS_EDITING; - - vec d; // vector of direction we ideally want to move in - - d.x = (float)(pl->move*cos(rad(pl->yaw-90))); - d.y = (float)(pl->move*sin(rad(pl->yaw-90))); - d.z = 0; - - if(floating || water) - { - d.x *= (float)cos(rad(pl->pitch)); - d.y *= (float)cos(rad(pl->pitch)); - d.z = (float)(pl->move*sin(rad(pl->pitch))); - }; - - d.x += (float)(pl->strafe*cos(rad(pl->yaw-180))); - d.y += (float)(pl->strafe*sin(rad(pl->yaw-180))); - - const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed; - const float friction = water ? 20.0f : (pl->onfloor || floating ? 6.0f : 30.0f); - - const float fpsfric = friction/curtime*20.0f; - - vmul(pl->vel, fpsfric-1); // slowly apply friction and direction to velocity, gives a smooth movement - vadd(pl->vel, d); - vdiv(pl->vel, fpsfric); - d = pl->vel; - vmul(d, speed); // d is now frametime based velocity vector - - pl->blocked = false; - pl->moving = true; - - if(floating) // just apply velocity - { - vadd(pl->o, d); - if(pl->jumpnext) { pl->jumpnext = false; pl->vel.z = 2; } - } - else // apply velocity with collision - { - if(pl->onfloor || water) - { - if(pl->jumpnext) - { - pl->jumpnext = false; - pl->vel.z = 1.7f; // physics impulse upwards - if(water) { pl->vel.x /= 8; pl->vel.y /= 8; }; // dampen velocity change even harder, gives correct water feel - if(local) playsoundc(S_JUMP); - else if(pl->monsterstate) playsound(S_JUMP, &pl->o); - else if(pl->bIsBot) botplaysound(S_JUMP, pl); // Added by Rick - } - else if(pl->timeinair>800) // if we land after long time must have been a high jump, make thud sound - { - if(local) playsoundc(S_LAND); - else if(pl->monsterstate) playsound(S_LAND, &pl->o); - else if(pl->bIsBot) botplaysound(S_LAND, pl); // Added by Rick - }; - pl->timeinair = 0; - } - else - { - pl->timeinair += curtime; - }; - - const float gravity = 20; - const float f = 1.0f/moveres; - float dropf = ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine - if(water) { dropf = 5; pl->timeinair = 0; }; // float slowly down in water - const float drop = dropf*curtime/gravity/100/moveres; // at high fps, gravity kicks in too fast - const float rise = speed/moveres/1.2f; // extra smoothness when lifting up stairs - - loopi(moveres) // discrete steps collision detection & sliding - { - // try move forward - pl->o.x += f*d.x; - pl->o.y += f*d.y; - pl->o.z += f*d.z; - if(collide(pl, false, drop, rise)) continue; - // player stuck, try slide along y axis - pl->blocked = true; - pl->o.x -= f*d.x; - if(collide(pl, false, drop, rise)) { d.x = 0; continue; }; - pl->o.x += f*d.x; - // still stuck, try x axis - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) { d.y = 0; continue; }; - pl->o.y += f*d.y; - // try just dropping down - pl->moving = false; - pl->o.x -= f*d.x; - pl->o.y -= f*d.y; - if(collide(pl, false, drop, rise)) { d.y = d.x = 0; continue; }; - pl->o.z -= f*d.z; - break; - }; - }; - - // detect wether player is outside map, used for skipping zbuffer clear mostly - - if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) - { - pl->outsidemap = true; - } - else - { - sqr *s = S((int)pl->o.x, (int)pl->o.y); - pl->outsidemap = SOLID(s) - || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) - || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); - }; - - // automatically apply smooth roll when strafing - - if(pl->strafe==0) - { - pl->roll = pl->roll/(1+(float)sqrt((float)curtime)/25); - } - else - { - pl->roll += pl->strafe*curtime/-30.0f; - if(pl->roll>maxroll) pl->roll = (float)maxroll; - if(pl->roll<-maxroll) pl->roll = (float)-maxroll; - }; - - // play sounds on water transitions - - if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } - else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o); - pl->inwater = water; - - // Added by Rick: Easy hack to store previous locations of all players/monsters/bots - pl->PrevLocations.Update(pl->o); - // End add -}; - -void moveplayer(dynent *pl, int moveres, bool local) -{ - loopi(physicsrepeat) moveplayer(pl, moveres, local, i ? curtime/physicsrepeat : curtime-curtime/physicsrepeat*(physicsrepeat-1)); -}; - +// physics.cpp: no physics books were hurt nor consulted in the construction of this code. +// All physics computations and constants were invented on the fly and simply tweaked until +// they "felt right", and have no basis in reality. Collision detection is simplistic but +// very robust (uses discrete steps at fixed fps). + +#include "cube.h" + +bool plcollide(dynent *d, dynent *o, float &headspace) // collide with player or monster +{ + if(o->state!=CS_ALIVE) return true; + const float r = o->radius+d->radius; + if(fabs(o->o.x-d->o.x)o.y-d->o.y)o.z-d->o.z)aboveeye+d->eyeheight) return false; + if(d->monsterstate) return false; // hack + headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; + if(headspace<0) headspace = 10; + }; + return true; +}; + +bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs) // recursively collide with a mipmapped corner cube +{ + sqr *w = wmip[mip]; + int sz = ssize>>mip; + bool stest = SOLID(SWS(w, x+dx, y, sz)) && SOLID(SWS(w, x, y+dy, sz)); + mip++; + x /= 2; + y /= 2; + if(SWS(wmip[mip], x, y, ssize>>mip)->type==CORNER) + { + bx = x<radius; + if(fabs(e.x-d->o.x)o.y)floor+mmi.zoff+e.attr3); + if(d->o.z-d->eyeheightlo) lo = mmz+mmi.h; + }; + }; +}; + +// all collision happens here +// spawn is a dirty side effect used in spawning +// drop & rise are supplied by the physics below to indicate gravity/push for current mini-timestep + +bool collide(dynent *d, bool spawn, float drop, float rise) +{ + const float fx1 = d->o.x-d->radius; // figure out integer cube rectangle this entity covers in map + const float fy1 = d->o.y-d->radius; + const float fx2 = d->o.x+d->radius; + const float fy2 = d->o.y+d->radius; + const int x1 = fast_f2nat(fx1); + const int y1 = fast_f2nat(fy1); + const int x2 = fast_f2nat(fx2); + const int y2 = fast_f2nat(fy2); + float hi = 127, lo = -128; + float minfloor = (d->monsterstate && !spawn && d->health>100) ? d->o.z-d->eyeheight-4.5f : -1000.0f; // big monsters are afraid of heights, unless angry :) + + for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map + { + if(OUTBORD(x,y)) return false; + sqr *s = S(x,y); + float ceil = s->ceil; + float floor = s->floor; + switch(s->type) + { + case SOLID: + return false; + + case CORNER: + { + int bx = x, by = y, bs = 1; + if(x==x1 && y==y1 && cornertest(0, x, y, -1, -1, bx, by, bs) && fx1-bx+fy1-by<=bs + || x==x2 && y==y1 && cornertest(0, x, y, 1, -1, bx, by, bs) && fx2-bx>=fy1-by + || x==x1 && y==y2 && cornertest(0, x, y, -1, 1, bx, by, bs) && fx1-bx<=fy2-by + || x==x2 && y==y2 && cornertest(0, x, y, 1, 1, bx, by, bs) && fx2-bx+fy2-by>=bs) + return false; + break; + }; + + case FHF: // FIXME: too simplistic collision with slopes, makes it feels like tiny stairs + floor -= (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; + break; + + case CHF: + ceil += (s->vdelta+S(x+1,y)->vdelta+S(x,y+1)->vdelta+S(x+1,y+1)->vdelta)/16.0f; + + }; + if(ceillo) lo = floor; + if(flooreyeheight+d->aboveeye) return false; + + float headspace = 10; + loopv(players) // collide with other players + { + dynent *o = players[i]; + if(!o || o==d) continue; + if(!plcollide(d, o, headspace)) return false; + }; + if(d!=player1) if(!plcollide(d, player1, headspace)) return false; + headspace -= 0.01f; + + mmcollide(d, hi, lo); // collide with map models + + if(spawn) + { + d->o.z = lo+d->eyeheight; // just drop to floor (sideeffect) + d->startheight = d->o.z; //no falling damage on spawn + d->onfloor = true; + } + else + { + const float space = d->o.z-d->eyeheight-lo; + if(space<0) + { + if(space>-0.01) d->o.z = lo+d->eyeheight; // stick on step + else if(space>-1.26f) d->o.z += rise; // rise thru stair + else return false; + } + else + { + d->o.z -= min(min(drop, space), headspace); // gravity + }; + + const float space2 = hi-(d->o.z+d->aboveeye); + if(space2<0) + { + if(space2<-0.1) return false; // hack alert! + d->o.z = hi-d->aboveeye; // glue to ceiling + d->vel.z = 0; // cancel out jumping velocity + }; + + d->onfloor = d->o.z-d->eyeheight-lo<0.01f; + }; + return true; +} + +float rad(float x) { return x*3.14159f/180; }; + +VAR(maxroll, 0, 3, 20); + +int physicsfraction = 0, physicsrepeat = 0; +const int MINFRAMETIME = 20; // physics always simulated at 50fps or better + +void physicsframe() // optimally schedule physics frames inside the graphics frames +{ + if(curtime>=MINFRAMETIME) + { + int faketime = curtime+physicsfraction; + physicsrepeat = faketime/MINFRAMETIME; + physicsfraction = faketime-physicsrepeat*MINFRAMETIME; + } + else + { + physicsrepeat = 1; + }; +}; + +void selfdamage(dynent * d, int dm) +{ + 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, dm, 1000, d->o); //edit out? + demodamage(dm, d->o); +}; + + +// main physics routine, moves a player/monster for a curtime step +// moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) +// local is false for multiplayer prediction + +void moveplayer(dynent *pl, int moveres, bool local, int curtime) +{ + const bool water = hdr.waterlevel>pl->o.z-0.5f; + const bool floating = (editmode && local) || pl->state==CS_EDITING; + + vec d; // vector of direction we ideally want to move in + + d.x = (float)(pl->move*cos(rad(pl->yaw-90))); + d.y = (float)(pl->move*sin(rad(pl->yaw-90))); + d.z = 0; + + if(floating || water) + { + d.x *= (float)cos(rad(pl->pitch)); + d.y *= (float)cos(rad(pl->pitch)); + d.z = (float)(pl->move*sin(rad(pl->pitch))); + }; + + d.x += (float)(pl->strafe*cos(rad(pl->yaw-180))); + d.y += (float)(pl->strafe*sin(rad(pl->yaw-180))); + + const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed; + const float friction = water ? 20.0f : (pl->onfloor || floating ? 6.0f : 30.0f); + + const float fpsfric = friction/curtime*20.0f; + + vmul(pl->vel, fpsfric-1); // slowly apply friction and direction to velocity, gives a smooth movement + vadd(pl->vel, d); + vdiv(pl->vel, fpsfric); + d = pl->vel; + vmul(d, speed); // d is now frametime based velocity vector + + pl->blocked = false; + pl->moving = true; + + if(floating) // just apply velocity + { + vadd(pl->o, d); + if(pl->jumpnext) { pl->jumpnext = false; pl->vel.z = 2; } + } + else // apply velocity with collision + { + if(pl->onfloor || water) + { + if (pl->onfloor || !pl->vel.z) + { + int damage = (int)pl->startheight - (int)pl->o.z; + if (damage > 8 && local) //try adding "&& local" if falling not fixed + { + selfdamage(damage,-1,pl); + demodamage(damage, player1->o); + playsound(S_FALL1+rnd(2), &pl->o); + }; + pl->startheight=pl->o.z; + }; + + if(pl->jumpnext) + { + pl->jumpnext = false; + pl->vel.z = 1.7f; // physics impulse upwards + if(water) { pl->vel.x /= 8; pl->vel.y /= 8; }; // dampen velocity change even harder, gives correct water feel + if(local) playsoundc(S_JUMP); + else if(pl->monsterstate) playsound(S_JUMP, &pl->o); + } + else if(pl->timeinair>800) // if we land after long time must have been a high jump, make thud sound + { + if(local) playsoundc(S_LAND); + else if(pl->monsterstate) playsound(S_LAND, &pl->o); + }; + pl->timeinair = 0; + } + else + { + pl->timeinair += curtime; + }; + + const float gravity = 20; + const float f = 1.0f/moveres; + float dropf = ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine + if(water) { dropf = 5; pl->timeinair = 0; }; // float slowly down in water + const float drop = dropf*curtime/gravity/100/moveres; // at high fps, gravity kicks in too fast + const float rise = speed/moveres/1.2f; // extra smoothness when lifting up stairs + + loopi(moveres) // discrete steps collision detection & sliding + { + // try move forward + pl->o.x += f*d.x; + pl->o.y += f*d.y; + pl->o.z += f*d.z; + if(collide(pl, false, drop, rise)) continue; + // player stuck, try slide along y axis + pl->blocked = true; + pl->o.x -= f*d.x; + if(collide(pl, false, drop, rise)) { d.x = 0; continue; }; + pl->o.x += f*d.x; + // still stuck, try x axis + pl->o.y -= f*d.y; + if(collide(pl, false, drop, rise)) { d.y = 0; continue; }; + pl->o.y += f*d.y; + // try just dropping down + pl->moving = false; + pl->o.x -= f*d.x; + pl->o.y -= f*d.y; + if(collide(pl, false, drop, rise)) { d.y = d.x = 0; continue; }; + pl->o.z -= f*d.z; + break; + }; + }; + + // detect wether player is outside map, used for skipping zbuffer clear mostly + + if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) + { + pl->outsidemap = true; + } + else + { + sqr *s = S((int)pl->o.x, (int)pl->o.y); + pl->outsidemap = SOLID(s) + || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) + || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); + }; + + // automatically apply smooth roll when strafing + + if(pl->strafe==0) + { + pl->roll = pl->roll/(1+(float)sqrt((float)curtime)/25); + } + else + { + pl->roll += pl->strafe*curtime/-30.0f; + if(pl->roll>maxroll) pl->roll = (float)maxroll; + if(pl->roll<-maxroll) pl->roll = (float)-maxroll; + }; + + // play sounds on water transitions + + if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } + else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o); + pl->inwater = water; +}; + +void moveplayer(dynent *pl, int moveres, bool local) +{ + loopi(physicsrepeat) moveplayer(pl, moveres, local, i ? curtime/physicsrepeat : curtime-curtime/physicsrepeat*(physicsrepeat-1)); +}; + diff --git a/source/src/protos.h b/source/src/protos.h index d0721b0f..382fa6cb 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -17,7 +17,7 @@ extern char *getalias(char *name); // console extern void keypress(int code, bool isdown, int cooked); extern void renderconsole(); -// extern void conoutf(const char *s, int a = 0, int b = 0, int c = 0); Moved to cube.h by Rick +extern void conoutf(const char *s, int a = 0, int b = 0, int c = 0); extern char *getcurcommand(); // menus @@ -84,7 +84,6 @@ extern char *getclientmap(); extern const char *modestr(int n); extern void zapdynent(dynent *&d); extern dynent *getclient(int cn); -extern dynent *getbot(int cn); // Added by Rick extern void timeupdate(int timeremain); extern void resetmovement(dynent *d); extern void fixplayer1range(); @@ -164,8 +163,7 @@ extern void damageblend(int n); // renderparticles extern void setorient(vec &r, vec &u); extern void particle_splash(int type, int num, int fade, vec &p); -//extern void particle_splash(int num, int fade, vec &p); -// extern void particle_trail(int type, int fade, vec &from, vec &to); Moved to cube.h by Rick +extern void particle_trail(int type, int fade, vec &from, vec &to); extern void render_particles(int time); // worldio @@ -193,16 +191,11 @@ extern void playsound(int n, vec *loc = 0); extern void playsoundc(int n); extern void initsound(); extern void cleansound(); -extern void botplaysound(int n, dynent *b); // Added by Rick // rendermd2 extern void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, float y, float z, float yaw, float pitch, bool teammate, float scale, float speed, int snap = 0, int basetime = 0); extern mapmodelinfo &getmminfo(int i); -// rendermd3 -extern void rendermd3player(dynent *d); -extern void md3setanim(dynent *d, int anim); - // server extern void initserver(bool dedicated, bool listen, int uprate, char *sdesc, char *ip, char *master, char *passwd); extern void cleanupserver(); @@ -231,22 +224,6 @@ extern void moveprojectiles(float time); extern void projreset(); extern char *playerincrosshair(); extern int reloadtime(int gun); -extern int delaytime(int gun); -// Added by Rick -extern char *botincrosshair(); -extern bool intersect(dynent *d, vec &from, vec &to, vec *end = NULL); -// End add by Rick - -/* -// monster -extern void monsterclear(); -extern void restoremonsterstate(); -extern void monsterthink(); -extern void monsterrender(); -extern dvector &getmonsters(); -extern void monsterpain(dynent *m, int damage, dynent *d); -extern void endsp(bool allkilled); -*/ // entities extern void renderents(); @@ -256,10 +233,8 @@ extern void renderentities(); extern void resetspawns(); extern void setspawn(int i, bool on); extern void baseammo(int gun); -// Added by Rick -extern void botbaseammo(int gun, dynent *d); -extern bool intersect(entity *e, vec &from, vec &to, vec *end=NULL); -// End add by Rick +extern void checkitems(); +extern void radd(dynent *d); // rndmap extern void perlinarea(block &b, int scale, int seed, int psize); diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index 996bd68b..d07ecc27 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -142,7 +142,7 @@ string closeent; char *entnames[] = { "none?", "light", "playerstart", - "primary", "secondary", "grenade", + "shotgun", "submachinegun", "sniperrifle", "assultrifle", "grenade", "pistol", "health", "armour", "quaddamage", "mapmodel", "trigger", "ladder", "?", "?", "?", "?", @@ -352,12 +352,12 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glPushMatrix(); glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1); draw_textf("%d", 90, 827, 2, player1->health); - if(player1->hasarmour) draw_textf("%d", 390, 827, 2, player1->armour); + if(player1->armour) draw_textf("%d", 390, 827, 2, player1->armour); //draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]); if (!player1->reloading && player1->gunselect!=GUN_KNIFE) { //draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]); - char gunstats[64]; + char * gunstats; sprintf(gunstats,"%i/%i",player1->mag[player1->gunselect],player1->ammo[player1->gunselect]); draw_text(gunstats, 690, 827, 2); //clean up pointer? @@ -369,14 +369,15 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glPushMatrix(); glOrtho(0, VIRTW, VIRTH, 0, -1, 1); glDisable(GL_BLEND); - drawicon(64, 0, 20, 1650); - if(player1->hasarmour) drawicon(128, 0, 620, 1650); + drawicon(128, 128, 20, 1650); + if(player1->armour) drawicon((float)(player1->armourtype*64), 0, 620, 1650); int g = player1->gunselect; - int r = 64; + int r = 64; if(g>2) { g -= 3; r = 128; }; drawicon((float)(g*64), (float)r, 1220, 1650); glPopMatrix(); }; + glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 6191e1e7..a5a7786f 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -106,7 +106,7 @@ int texy[MAXTEX]; string texname[MAXTEX]; int curtex = 0; const int FIRSTTEX = 100; // opengl id = loaded id + FIRSTTEX -// std 1+, sky 14+, md3s 20+, mdls 30+ +// std 1+, sky 14+, mdls 20+ const int MAXFRAMES = 2; // increase to allow more complex shader defs int mapping[256][MAXFRAMES]; // ( cube texture, frame ) -> ( opengl id, name ) @@ -370,8 +370,6 @@ void gl_drawframe(int w, int h, float changelod, float curfps) xtraverts = 0; renderclients(); - //monsterrender(); - BotManager.RenderBots(); // Added by Rick renderentities(); @@ -380,12 +378,6 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glDisable(GL_CULL_FACE); - // Added by Rick: Need todo here because of drawing the waypoints - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - WaypointClass.Think(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - // end add - drawhudgun(fovy, aspect, farplane); overbright(1); diff --git a/source/src/rendermd2.cpp b/source/src/rendermd2.cpp index 7a3296fb..5e067889 100644 --- a/source/src/rendermd2.cpp +++ b/source/src/rendermd2.cpp @@ -193,7 +193,7 @@ void md2::render(vec &light, int frame, int range, float x, float y, float z, fl hashtable *mdllookup = NULL; vector mapmodels; -const int FIRSTMDL = 30; +const int FIRSTMDL = 20; void delayedload(md2 *m) { @@ -279,6 +279,5 @@ void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, f }; */ - m->render(light, frame, range, x, y, z, yaw, pitch, scale, speed, snap, basetime); - //testrender(x, y, z, yaw, pitch, 1.0f); + m->render(light, frame, range, x, y, z, yaw, pitch, scale, speed, snap, basetime); }; diff --git a/source/src/savegamedemo.cpp b/source/src/savegamedemo.cpp index ac9f6663..7cc79d41 100644 --- a/source/src/savegamedemo.cpp +++ b/source/src/savegamedemo.cpp @@ -35,15 +35,6 @@ void stop() demoloading = false; loopv(playerhistory) zapdynent(playerhistory[i]); playerhistory.setsize(0); - // Added by Rick: Remove bots - loopv(bots) - { - if (!bots[i]) continue; - delete bots[i]->pBot; - bots[i]->pBot = NULL; - zapdynent(bots[i]); - } - bots.setsize(0); }; void stopifrecording() { if(demorecording) stop(); }; @@ -114,33 +105,17 @@ void loadgamerest() { if(demoplayback || !f) return; - //Modified by Rick, MSVC 6.0 doesnt seem to like this - //if(gzgeti()!=ents.length()) return loadgameout(); - if(gzgeti()!=ents.length()) { loadgameout(); return; } + if(gzgeti()!=ents.length()) return loadgameout(); loopv(ents) { ents[i].spawned = gzgetc(f)!=0; - if(ents[i].type==TRIGGER && !ents[i].spawned) trigger(ents[i].attr1, ents[i].attr2, true); + if(ents[i].type==CARROT && !ents[i].spawned) trigger(ents[i].attr1, ents[i].attr2, true); }; restoreserverstate(ents); gzread(f, player1, sizeof(dynent)); player1->lastaction = lastmillis; - int nmonsters = gzgeti(); - //dvector &monsters = getmonsters(); - //Modified by Rick, MSVC 6.0 doesnt seem to like this - //if(nmonsters!=monsters.length()) return loadgameout(); - //if(nmonsters!=monsters.length()) { loadgameout(); return; } - //loopv(monsters) - //{ - //gzread(f, monsters[i], sizeof(dynent)); - //monsters[i]->enemy = player1; // lazy, could save id of enemy instead - //monsters[i]->lastaction = monsters[i]->trigger = lastmillis+500; // also lazy, but no real noticable effect on game - //if(monsters[i]->state==CS_DEAD) monsters[i]->lastaction = 0; - //}; - //restoremonsterstate(); - int nplayers = gzgeti(); loopi(nplayers) if(!gzget()) { @@ -191,7 +166,7 @@ void incomingdemodata(uchar *buf, int len, bool extras) gzputi(player1->gunwait); gzputi(player1->health); gzputi(player1->armour); - gzput(player1->hasarmour); + gzput(player1->armourtype); loopi(NUMGUNS) gzput(player1->ammo[i]); gzput(player1->state); gzputi(bdamage); @@ -296,7 +271,7 @@ void demoplaybackstep() target->gunwait = gzgeti(); target->health = gzgeti(); target->armour = gzgeti(); - target->hasarmour = gzget(); + target->armourtype = gzget(); loopi(NUMGUNS) target->ammo[i] = gzget(); target->state = gzget(); target->lastmove = playbacktime; diff --git a/source/src/server.cpp b/source/src/server.cpp index 6e98ecfe..a3406004 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -13,31 +13,23 @@ struct client // server side version of "dynent" type string mapvote; string name; int modevote; - // Added by Rick: For bot voting - bool addbot, kickbot, changebotskill; - short botcount; - string botteam, botname; - short botskill; - bool kickallbots; - // End add }; vector clients; string smapname; +struct server_entity // server side version of "entity" type +{ + bool spawned; + int spawnsecs; +}; + vector sents; bool notgotitems = true; // true when map has changed and waiting for clients to send item int mode = 0; -// Added by Rick -#ifndef STANDALONE -extern void kickbot(const char *szName); -extern void kickallbots(void); -#endif -// End add - void restoreserverstate(vector &ents) // hack: called from savegame code, only works in SP { loopv(sents) @@ -153,206 +145,6 @@ bool vote(char *map, int reqmode, int sender) return true; }; -// Added by Rick: Vote for bot commands -void resetbotvotes() -{ - loopv(clients) - { - clients[i].addbot = false; - clients[i].kickbot = false; - clients[i].changebotskill = false; - clients[i].kickallbots = false; - clients[i].botcount = 0; - clients[i].botteam[0] = 0; - clients[i].botname[0] = 0; - clients[i].botskill = -1; - } -}; - -bool addbotvote(int count, char *team, int skill, char *name, int sender) -{ -#ifndef STANDALONE - clients[sender].addbot = true; - clients[sender].kickbot = false; - clients[sender].changebotskill = false; - clients[sender].botcount = (count>=0) ? count : 0; - if (team && team[0]) strcpy_s(clients[sender].botteam, team); - else clients[sender].botteam[0] = 0; - clients[sender].botskill = skill; - if (name && name[0]) strcpy_s(clients[sender].botname, name); - else clients[sender].botname[0] = 0; - int yes = 0, no = 0; - loopv(clients) if(clients[i].type!=ST_EMPTY) - { - if (clients[i].addbot) - { - if (!strcmp(clients[i].botteam, team) && !strcmp(clients[i].botname, name) && - (clients[i].botskill == skill) && - (clients[i].botcount == clients[sender].botcount)) - yes++; - else - no++; - } - else no++; - } - if(yes==1 && no==0) return true; // single player - sprintf_sd(msg)("%s suggests to add a bot", clients[sender].name); - if (team && team[0]) - { - strcat(msg, " on team "); - strcat(msg, team); - } - - if (skill!=-1) - { - strcat(msg, ", with skill "); - strcat(msg, SkillNrToSkillName(skill)); - } - - if (name && name[0]) - { - strcat(msg, " named "); - strcat(msg, name); - } - - sendservmsg(msg); - if(yes/(float)(yes+no) <= 0.5f) return false; - sendservmsg("vote passed"); - resetbotvotes(); -#endif - return true; -}; - -bool kickbotvote(int specific, char *name, int sender) -{ - clients[sender].addbot = false; - clients[sender].kickbot = true; - clients[sender].changebotskill = false; - clients[sender].kickallbots = !specific; - if (name && name[0]) strcpy_s(clients[sender].botname, name); - else clients[sender].botname[0] = 0; - int yes = 0, no = 0; - loopv(clients) if(clients[i].type!=ST_EMPTY) - { - if (clients[i].kickbot) - { - if (clients[sender].kickallbots) - { - if (clients[i].kickallbots) yes++; - else no++; - } - else - { - if (!clients[i].kickallbots && !strcmp(clients[i].botname, name)) - yes++; - else - no++; - } - } - else no++; - } - if(yes==1 && no==0) return true; // single player - - char msg[256]; - if (clients[sender].kickallbots) - sprintf(msg, "%s suggests to kick all bots", clients[sender].name); - else - sprintf(msg, "%s suggests to kick bot %s", clients[sender].name, - clients[sender].botname); - - sendservmsg(msg); - if(yes/(float)(yes+no) <= 0.5f) return false; - sendservmsg("vote passed"); - resetbotvotes(); - return true; -}; - -bool botskillvote(int skill, int sender) -{ -#ifndef STANDALONE - clients[sender].addbot = false; - clients[sender].kickbot = false; - clients[sender].changebotskill = true; - clients[sender].botskill = skill; - int yes = 0, no = 0; - loopv(clients) if(clients[i].type!=ST_EMPTY) - { - if (clients[i].changebotskill) - { - if (clients[sender].botskill == clients[i].botskill) yes++; - else no++; - } - else no++; - } - if(yes==1 && no==0) return true; // single player - - sprintf_sd(msg)("%s suggests to change the skill of all bots to: %s", clients[sender].name, - SkillNrToSkillName(clients[sender].botskill)); - sendservmsg(msg); - if(yes/(float)(yes+no) <= 0.5f) return false; - sendservmsg("vote passed"); - resetbotvotes(); -#endif - return true; -}; - -void botcommand(uchar *&p, char *text, int sender) -{ - int type = getint(p); - switch(EBotCommands(type)) - { - case COMMAND_ADDBOT: - { - string name, team; - int count = getint(p); - int skill = getint(p); - sgetstr(); - strcpy(team, text); - sgetstr(); - strcpy(name, text); -#ifndef STANDALONE - if (addbotvote(count, team, skill, name, sender)) - { - while(count>0) - { - BotManager.CreateBot(team, SkillNrToSkillName(skill), name); - count--; - } - } -#endif - break; - } - case COMMAND_KICKBOT: - { - int specific = getint(p); - - if (specific) - sgetstr(); -#ifndef STANDALONE - if (kickbotvote(specific, text, sender)) - { - if (specific) - kickbot(text); - else - kickallbots(); - } -#endif - } - case COMMAND_BOTSKILL: - { - int skill = getint(p); -#ifndef STANDALONE - if (botskillvote(skill, sender)) - { - BotManager.ChangeBotSkill(skill, NULL); - } -#endif - } - } -} - -// End add - // server side processing of updates: does very little and most state is tracked client only // could be extended to move more gameplay to server (at expense of lag) @@ -415,13 +207,7 @@ void process(ENetPacket * packet, int sender) // sender may be -1 case SV_ITEMPICKUP: { int n = getint(p); - // pickup(n, getint(p), sender); Modified by Rick - int spawnsec = getint(p); - - if (getint(p)) // Only call pickup() if this isn't a bot - pickup(n, spawnsec, sender); - // End mod - + pickup(n, getint(p), sender); break; }; @@ -455,21 +241,6 @@ void process(ENetPacket * packet, int sender) // sender may be -1 send(sender, recvmap(sender)); return; - // Added by Rick: Bot specifc messages - case SV_ADDBOT: - getint(p); - sgetstr(); - //strcpy_s(clients[cn].name, text); - sgetstr(); - getint(p); - break; - case SV_BOTCOMMAND: // Client asked server for a bot command - { - botcommand(p, text, sender); - break; - } - // End add by Rick - case SV_EXT: // allows for new features that require no server updates { for(int n = getint(p); n; n--) getint(p); @@ -551,7 +322,6 @@ void resetserverifempty() clients.setsize(0); smapname[0] = 0; resetvotes(); - resetbotvotes(); // Added by Rick resetitems(); mode = 0; mapreload = false; @@ -634,9 +404,6 @@ void serverslice(int seconds, unsigned int timeout) // main server update, cal send2(true, -1, SV_CDIS, (int)event.peer->data); event.peer->data = (void *)-1; break; - - default: - break; }; }; diff --git a/source/src/serverutil.cpp b/source/src/serverutil.cpp index a378566c..1f9e25c6 100644 --- a/source/src/serverutil.cpp +++ b/source/src/serverutil.cpp @@ -29,17 +29,17 @@ void sendstring(char *t, uchar *&p) const char *modenames[] = { "team deathmatch", "coopedit", "deathmatch", "survior", - "team survior", "ctf", "pistols", + "team survior", "ctf", }; //const char *modestr(int n) { return (n>=-2 && n<12) ? modenames[n+2] : "unknown"; }; -const char *modestr(int n) { return (n>=0 && n<7) ? modenames[n] : "unknown"; }; +const char *modestr(int n) { return (n>=0 && n<6) ? modenames[n] : "unknown"; }; + -/* Modified by Rick: New messages and different sizes for existing ones char msgsizesl[] = // size inclusive message token, 0 for variable or not-checked sizes { SV_INITS2C, 4, SV_INITC2S, 0, SV_POS, 12, SV_TEXT, 0, SV_SOUND, 2, SV_CDIS, 2, - SV_DIED, 2, SV_DAMAGE, 4, SV_SHOsT, 8, SV_FRAGS, 2, + SV_DIED, 2, SV_DAMAGE, 4, SV_SHOT, 8, SV_FRAGS, 2, SV_TIMEUP, 2, SV_EDITENT, 10, SV_MAPRELOAD, 2, SV_ITEMACC, 2, SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 3, SV_DENIED, 2, SV_PING, 2, SV_PONG, 2, SV_CLIENTPING, 2, SV_GAMEMODE, 2, @@ -48,24 +48,6 @@ char msgsizesl[] = // size inclusive message token, 0 for variable SV_EXT, 0, -1 }; -*/ - -char msgsizesl[] = // size inclusive message token, 0 for variable or not-checked sizes -{ - SV_INITS2C, 4, SV_INITC2S, 0, SV_POS, 12, SV_TEXT, 0, SV_SOUND, 2, SV_CDIS, 2, - SV_DIED, 3, SV_DAMAGE, 6, SV_SHOT, 9, SV_FRAGS, 2, - SV_TIMEUP, 2, SV_EDITENT, 10, SV_MAPRELOAD, 2, SV_ITEMACC, 2, - SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 4, 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, - // Added by Rick: Bot specific messages - SV_BOTSOUND, 3, SV_BOTDIS, 2, SV_BOTDIED, 4, SV_CLIENT2BOTDMG, 4, SV_BOT2BOTDMG, 2, - SV_BOTFRAGS, 3, SV_ADDBOT, 5, SV_BOTUPDATE, 12, SV_BOTCOMMAND, 0, - // End add - SV_EXT, 0, - -1 -}; char msgsizelookup(int msg) { diff --git a/source/src/sound.cpp b/source/src/sound.cpp index 35fb118d..26ec40cf 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -125,13 +125,6 @@ COMMAND(registersound, ARG_1EST); void playsoundc(int n) { addmsg(0, 2, SV_SOUND, n); playsound(n); }; -// Added by Rick: For bots -void botplaysound(int n, dynent *b) -{ - addmsg(0, 3, SV_BOTSOUND, n, BotManager.GetBotIndex(b)); playsound(n, &b->o); -} -// End add by Rick - int soundsatonce = 0, lastsoundmillis = 0; void playsound(int n, vec *loc) diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index ec76f825..446b004d 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -13,15 +13,14 @@ guninfo guns[NUMGUNS] = { { S_KNIFE, S_NULL, 0, 250, 50, 0, 0, 1, 1, 1, "knife" }, { S_PISTOL, S_RPISTOL, 1400, 170, 20, 0, 0, 20, 10, 8, "pistol" }, // *SGRAYS - { S_SHOTGUN, S_RSHOTGUN, 2400, 1100, 6, 0, 0, 1, 35, 7, "shotgun" }, //reload time is for 1 shell from 7 too powerful to 6 - { S_SUBGUN, S_RSUBGUN, 1650, 90, 14, 0, 0, 45, 15, 30, "subgun" }, + { S_SHOTGUN, S_RSHOTGUN, 2400, 1100, 7, 0, 0, 1, 35, 7, "shotgun" }, + { S_SUBGUN, S_RSUBGUN, 1650, 90, 12, 0, 0, 45, 15, 30, "subgun" }, { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, "sniper" }, - { S_ASSULT, S_RASSULT, 2000, 130, 33, 0, 0, 90, 40, 20, "assult" }, //recoil was 44 + { S_ASSULT, S_RASSULT, 2000, 130, 33, 0, 0, 90, 44, 20, "assult" }, { S_GRENADE, S_NULL, 0, 2000, 40, 30, 6, 1, 1, 1, "grenade" }, }; - //weapon selection void next() { @@ -51,25 +50,6 @@ void previous() COMMAND(next,ARG_NONE); COMMAND(previous,ARG_NONE); -void primary() -{ - player1->gunselect=player1->primary; -}; - -void secondary() -{ - player1->gunselect=GUN_PISTOL; -}; - -void melee() -{ - player1->gunselect=GUN_KNIFE; -}; - -COMMAND(primary,ARG_NONE); -COMMAND(secondary,ARG_NONE); -COMMAND(melee,ARG_NONE); - void reload() { if(player1->gunselect==GUN_KNIFE) return; @@ -80,14 +60,11 @@ void reload() player1->reloading = true; player1->lastaction = lastmillis; - int a = guns[player1->gunselect].magsize - player1->mag[player1->gunselect]; - player1->gunwait = guns[player1->gunselect].reloadtime; //temp hack in drawhudgun() so no guns drawn while reloading, needs fixed - - + int a = guns[player1->gunselect].magsize - player1->mag[player1->gunselect]; if (a >= player1->ammo[player1->gunselect]) { player1->mag[player1->gunselect] += player1->ammo[player1->gunselect]; @@ -105,7 +82,7 @@ void reload() COMMAND(reload,ARG_NONE); int reloadtime(int gun) { return guns[gun].attackdelay; }; -int delaytime(int gun) { return guns[gun].attackdelay; }; + void createrays(vec &from, vec &to) // create random spread of rays for the shotgun { @@ -120,8 +97,7 @@ void createrays(vec &from, vec &to) // create random spread of rays }; }; -//bool intersect(dynent *d, vec &from, vec &to) // if lineseg hits entity bounding box -bool intersect(dynent *d, vec &from, vec &to, vec *end) // if lineseg hits entity bounding box +bool intersect(dynent *d, vec &from, vec &to) // if lineseg hits entity bounding box { vec v = to, w = d->o, *p; vsub(v, from); @@ -142,25 +118,12 @@ bool intersect(dynent *d, vec &from, vec &to, vec *end) // if lineseg hits ent }; }; - /* Modified by Rick return p->x <= d->o.x+d->radius && p->x >= d->o.x-d->radius && p->y <= d->o.y+d->radius && p->y >= d->o.y-d->radius && p->z <= d->o.z+d->aboveeye && p->z >= d->o.z-d->eyeheight; - */ - if( p->x <= d->o.x+d->radius - && p->x >= d->o.x-d->radius - && p->y <= d->o.y+d->radius - && p->y >= d->o.y-d->radius - && p->z <= d->o.z+d->aboveeye - && p->z >= d->o.z-d->eyeheight) - { - if (end) *end = *p; - return true; - } - return false; }; char *playerincrosshair() @@ -175,20 +138,6 @@ char *playerincrosshair() return NULL; }; -// Added by Rick -char *botincrosshair() -{ - if(demoplayback) return NULL; - loopv(bots) - { - dynent *o = bots[i]; - if(!o) continue; - if(intersect(o, player1->o, worldpos)) return o->name; - }; - return NULL; -}; -// End add by Rick - const int MAXPROJ = 100; struct projectile { vec o, to; float speed; dynent *owner; int gun; bool inuse, local; }; projectile projs[MAXPROJ]; @@ -215,59 +164,9 @@ void newprojectile(vec &from, vec &to, float speed, bool local, dynent *owner, i void hit(int target, int damage, dynent *d, dynent *at) { if(d==player1) selfdamage(damage, at==player1 ? -1 : -2, at); - //else if(d->monsterstate) monsterpain(d, damage, at); - // Added by Rick: Let bots take damage - else if (d->pBot) d->pBot->BotPain(damage, at); - else if (d->bIsBot) - { - int PlayerIndex = -1; - if (at->bIsBot) PlayerIndex = BotManager.GetBotIndex(at); - else - { - loopv(players) - { - if (!players[i]) continue; - - if (players[i] == at) - { - PlayerIndex = i; - break; - } - } - } - - int msgtype = (at->bIsBot) ? SV_BOT2BOTDMG : SV_CLIENT2BOTDMG; - addmsg(1, 4, msgtype, BotManager.GetBotIndex(d), damage, PlayerIndex); - playsound(S_PAIN1+rnd(5), &d->o); - } - // End add by Rick - //else { addmsg(1, 4, SV_DAMAGE, target, damage, d->lifesequence); playsound(S_PAIN1+rnd(5), &d->o); }; Modified by Rick: Added IsBot and PlayerIndex to message - else - { - // Modified by Rick: Added IsBot and PlayerIndex to message - int PlayerIndex = -1; - if (at->bIsBot) - PlayerIndex = BotManager.GetBotIndex(at); - else - { - loopv(players) - { - if (!players[i]) - continue; - - if (players[i] == at) - { - PlayerIndex = i; - break; - } - } - } - addmsg(1, 6, SV_DAMAGE, target, damage, d->lifesequence, at->bIsBot, PlayerIndex); - playsound(S_PAIN1+rnd(5), &d->o); - }; - + else { addmsg(1, 4, SV_DAMAGE, target, damage, d->lifesequence); playsound(S_PAIN1+rnd(5), &d->o); }; particle_splash(3, damage, 1000, d->o); - demodamage(damage, d->o); + demodamage(damage, d->o); }; const float RL_RADIUS = 5; @@ -288,13 +187,11 @@ void radialeffect(dynent *o, vec &v, int cn, int qdam, dynent *at) }; }; -// Modified by Rick: Added notthisbot -void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismonster, int notthisbot, int qdam) +void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismonster, int qdam) { particle_splash(0, 50, 300, v); p->inuse = false; if(p->gun!=GUN_GRENADE) - if(p->gun!=GUN_GRENADE) //changed { playsound(S_FEXPLODE, &v); // no push? @@ -313,29 +210,15 @@ void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismons if(!o) continue; radialeffect(o, v, i, qdam, p->owner); }; - // Added by Rick - loopv(bots) - { - if(i==notthisbot) continue; - dynent *o = bots[i]; - if(!o) continue; - radialeffect(o, v, i, qdam, p->owner); - } - // End add by Rick - //dvector &mv = getmonsters(); - //loopv(mv) if(i!=notthismonster) radialeffect(mv[i], v, i, qdam, p->owner); - }; + }; }; -// Modified by Rick -// inline void projdamage(dynent *o, projectile *p, vec &v, int i, int im, int qdam) -inline void projdamage(dynent *o, projectile *p, vec &v, int i, int im, int ib, int qdam) +inline void projdamage(dynent *o, projectile *p, vec &v, int i, int im, int qdam) { if(o->state!=CS_ALIVE) return; if(intersect(o, p->o, v)) { - // splash(p, v, p->o, i, im, qdam); Modified by Rick - splash(p, v, p->o, i, im, ib, qdam); + splash(p, v, p->o, i, im, qdam); hit(i, qdam, o, p->owner); }; }; @@ -358,36 +241,17 @@ void moveprojectiles(float time) { dynent *o = players[i]; if(!o) continue; - // projdamage(o, p, v, i, -1, qdam); Modified by Rick - projdamage(o, p, v, i, -1, -1, qdam); + projdamage(o, p, v, i, -1, qdam); }; - // Added by Rick: Damage bots aswell - loopv(bots) - { - dynent *o = bots[i]; - if(!o || (o == p->owner)) continue; - projdamage(o, p, v, -1, -1, i, qdam); - }; - // End add by Rick - // if(p->owner!=player1) projdamage(player1, p, v, -1, -1, qdam); Modified by Rick - if(p->owner!=player1) projdamage(player1, p, v, -1, -1, -1, qdam); - //dvector &mv = getmonsters(); - //loopv(mv) if(!vreject(mv[i]->o, v, 10.0f) && mv[i]!=p->owner) projdamage(mv[i], p, v, -1, i, qdam); Modified by Rick - //loopv(mv) if(!vreject(mv[i]->o, v, 10.0f) && mv[i]!=p->owner) projdamage(mv[i], p, v, -1, i, -1, qdam); + if(p->owner!=player1) projdamage(player1, p, v, -1, -1, qdam); }; if(p->inuse) { - // if(time==dtime) splash(p, v, p->o, -1, -1, qdam); Modified by Rick - if(time==dtime) splash(p, v, p->o, -1, -1, -1, qdam); + if(time==dtime) splash(p, v, p->o, -1, -1, qdam); else { if(p->gun==GUN_GRENADE) { dodynlight(p->o, v, 0, 255, p->owner); particle_splash(5, 2, 200, v); } else { particle_splash(1, 1, 200, v); particle_splash(guns[p->gun].part, 1, 1, v); }; - // Added by Rick - traceresult_s tr; - TraceLine(p->o, v, p->owner, true, &tr); - if (tr.collided) splash(p, v, p->o, -1, -1, -1, qdam); - // End add }; }; p->o = v; @@ -423,7 +287,7 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local) // create vi case GUN_SNIPER: particle_splash(0, 50, 200, to); - //particle_trail(1, 500, from, to); + particle_trail(1, 500, from, to); break; }; }; @@ -462,12 +326,9 @@ void spreadandrecoil(vec & from, vec & to, dynent * d) //recoil int rcl = guns[d->gunselect].recoil*-0.01f; - if (d->gunselect==GUN_ASSULT) + if ((d->gunselect==GUN_ASSULT) && (d->shots<=3)) { - if (d->shots<=3) - spd = spd / 5; - - rcl += (rnd(8)*-0.01f); + spd = spd / 5; }; if ((d->gunselect==GUN_SNIPER) && (d->vel.x<.25f && d->vel.y<.25f)) @@ -478,11 +339,10 @@ void spreadandrecoil(vec & from, vec & to, dynent * d) if (d->gunselect!=GUN_SHOTGUN) //no spread on shotgun { + #define RNDD (rnd(spd)-spd/2)*f vec r = { RNDD, RNDD, RNDD }; vadd(to, r); }; - - //increase pitch for recoil vdiv(unitv, dist); @@ -508,24 +368,6 @@ void shoot(dynent *d, vec &targ) }; d->lastaction = lastmillis; d->lastattackgun = d->gunselect; - // Modified by Rick - // if(!d->mag[d->gunselect]) { playsoundc(S_NOAMMO); d->gunwait = 250; d->lastattackgun = -1; return; }; - - if(!d->mag[d->gunselect]) - { - if (d->bIsBot) botplaysound(S_NOAMMO, d); - else playsoundc(S_NOAMMO); - d->gunwait = 250; - d->lastattackgun = -1; - return; - }; - // End mod - - if (d->gunselect!=0) //if knife skip - { - if(d->gunselect) d->mag[d->gunselect]--; - } - if(!d->mag[d->gunselect]) { playsoundc(S_NOAMMO); d->gunwait = 250; d->lastattackgun = -1; return; }; if(d->gunselect) d->mag[d->gunselect]--; vec from = d->o; @@ -545,25 +387,10 @@ void shoot(dynent *d, vec &targ) }; if(d->gunselect==GUN_SHOTGUN) createrays(from, to); - //if(d->quadmillis && attacktime>200) playsoundc(S_ITEMPUP); Modified by Rick - if(d->quadmillis && attacktime>200) - { - if (d->bIsBot) botplaysound(S_ITEMPUP, d); - else playsoundc(S_ITEMPUP); - } - // End mod + if(d->quadmillis && attacktime>200) playsoundc(S_ITEMPUP); shootv(d->gunselect, from, to, d, true); - // Modified by Rick - // if(!d->monsterstate) addmsg(1, 8, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF)); - if(!d->monsterstate) - { - int index = -1; - if (d->bIsBot) - index = BotManager.GetBotIndex(d); - addmsg(1, 9, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), index); - } - // End mod - d->gunwait = delaytime(d->gunselect);// hack guns[d->gunselect].attackdelay; + addmsg(1, 8, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF)); + d->gunwait = guns[d->gunselect].attackdelay; if(guns[d->gunselect].projspeed) return; @@ -574,134 +401,4 @@ void shoot(dynent *d, vec &targ) raydamage(o, from, to, d, i); }; - // Added by Rick: raydamage on bots too - loopv(bots) - { - dynent *o = bots[i]; - if(!o || (o == d)) continue; - raydamage(o, from, to, d, i); - }; - // End add by Rick - - //dvector &v = getmonsters(); - //loopv(v) if(v[i]!=d) raydamage(v[i], from, to, d, -2); - - //if(d->monsterstate) raydamage(player1, from, to, d, -1); Modified by Rick - if(d->monsterstate || d->bIsBot) raydamage(player1, from, to, d, -1); }; - -//currently client side only, need to make serv -void additem(int gun) -{ - if (gun>0 && gun<10) - { -// player1->mag[gun] = guns[gun].magazine; -// player1->ammo[gun] = guns[gun].magazine * 3; - - }; - - if (gun==10) //helmet - { - conoutf("NO HELMET FOR YOU!"); -// player1->armour = 20 -// break; - }; - - if (gun==11) //armour - { - conoutf("you can't add armor yet!"); -// additem(I_ARMOUR, player1->armour, 20); -// break; - }; -}; - -COMMAND(additem,ARG_1INT); - - -//gotta find a neater way of doing this -argh -void altattack(bool on) -{ -/* - if (on) - { - switch(player1->gunselect) - { - case(GUN_KNIFE): - break; - case(GUN_SEMIPISTOL): - break; - case(GUN_SHOTGUN): - break; - case(GUN_SNIPER): - setvar("fov",getvar("fov")-55); - break; - case(GUN_SUBGUN): - break; - case(GUN_AUTORIFLE): - break; - case(GUN_GRENADE): - break; - }; - } - else - { - switch(player1->gunselect) - { - case(GUN_KNIFE): - break; - case(GUN_SEMIPISTOL): - break; - case(GUN_SHOTGUN): - break; - case(GUN_SNIPER): - setvar("fov",getvar("fov")+55); - break; - case(GUN_SUBGUN): - break; - case(GUN_AUTORIFLE): - break; - case(GUN_GRENADE): - break; - }; - }; - */ -}; - - -void altattack(void) -{ - player1->altattack = !player1->altattack; - - switch(player1->gunselect) - { - case(GUN_SHOTGUN): - if(player1->mag[player1->gunselect]>=guns[player1->gunselect].magsize) return; - if(player1->ammo[player1->gunselect]<=0) return; - if(player1->reloading) return; - - player1->reloading = true; - player1->lastaction = lastmillis; - - player1->gunwait = guns[player1->gunselect].reloadtime / 2; - - if(player1->ammo[GUN_SHOTGUN]>1) - player1->mag[GUN_SHOTGUN]++; - player1->ammo[GUN_SHOTGUN]--; - - playsoundc(guns[player1->gunselect].reload); - break; - - case(GUN_SNIPER): - if(player1->altattack) - setvar("fov",getvar("fov")-55); - else - setvar("fov",getvar("fov")+55); - break; - - - } - - -}; - -COMMAND(altattack, ARG_NONE); diff --git a/source/src/world.cpp b/source/src/world.cpp index a4f60def..46bbf811 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -37,16 +37,7 @@ void settag(int tag, int type) // set all cubes with "tag" to space, if }; void resettagareas() { settag(0, 0); }; // reset for editing or map saving -// Modified by Rick -//void settagareas() { settag(0, 1); loopv(ents) if(ents[i].type==TRIGGER) setspawn(i, true); }; // set for playing - -void settagareas() // set for playing -{ - settag(0, 1); - loopv(ents) if(ents[i].type==TRIGGER) setspawn(i, true); - if(ishost()) BotManager.PickNextTrigger(); -}; -// End mod +void settagareas() { settag(0, 1); loopv(ents) if(ents[i].type==CARROT) setspawn(i, true); }; // set for playing void trigger(int tag, int type, bool savegame) { @@ -316,8 +307,7 @@ void empty_world(int factor, bool force) // main empty world creation routine s->defer = 0; }; - //strncpy(hdr.head, "CUBE", 4); - strncpy(hdr.head, "ACMP", 4); + strncpy(hdr.head, "CUBE", 4); hdr.version = MAPVERSION; hdr.headersize = sizeof(header); hdr.sfactor = sfactor; diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index 5a786d5b..1c0ba2cf 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -242,7 +242,7 @@ void load_world(char *mname) // still supports all map formats that have }; - if (hdr.version