home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / entities.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-01  |  11.3 KB  |  408 lines

  1. // entities.cpp: map entity related functions (pickup etc.)
  2.  
  3. #include "cube.h"
  4.  
  5. vector<entity> ents;
  6.  
  7. char *entnames[] =
  8. {   
  9.     "none?", "light", "playerstart",
  10.     "clips", "ammobox","grenades",
  11.     "health", "armour", "akimbo",
  12.     "mapmodel", "trigger", 
  13.     "ladder", "ctf-flag", "?", "?", "?",
  14. };
  15. char *entmdlnames[] = 
  16. {
  17. //FIXME : fix the "pickups" infront
  18.     "pickups/pistolclips", "pickups/ammobox", "pickups/nades", "pickups/health", "pickups/kevlar", "pickups/akimbo",
  19. };
  20.  
  21. void renderent(entity &e, char *mdlname, float z, float yaw, int anim = ANIM_MAPMODEL|ANIM_LOOP, int basetime = 0, float speed = 0)
  22. {
  23.     rendermodel(mdlname, anim, 0, 1.1f, e.x, e.y, z+S(e.x, e.y)->floor, yaw, 0, speed, basetime);
  24. }
  25.  
  26. void renderentities()
  27. {
  28.     if(editmode) loopv(ents)
  29.     {
  30.         entity &e = ents[i];
  31.         if(e.type==NOTUSED) continue;
  32.         vec v(e.x, e.y, e.z); 
  33.         particle_splash(2, 2, 40, v);
  34.     }
  35.     loopv(ents)
  36.     {
  37.         entity &e = ents[i];
  38.         if(e.type==MAPMODEL)
  39.         {
  40.             mapmodelinfo &mmi = getmminfo(e.attr2);
  41.             if(!&mmi) continue;
  42.             rendermodel(mmi.name, ANIM_MAPMODEL|ANIM_LOOP, e.attr4, mmi.rad ? (float)mmi.rad : 1.1f, e.x, e.y, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 10.0f);
  43.         }
  44.         else if(m_ctf && e.type==CTF_FLAG)
  45.         {
  46.             flaginfo &f = flaginfos[e.attr2];
  47.             if(f.state==CTFF_STOLEN)
  48.             {
  49.                 if(!f.actor || f.actor == player1) continue;
  50.                 s_sprintfd(path)("pickups/flags/small_%s", team_string(e.attr2));
  51.                 rendermodel(path, ANIM_FLAG|ANIM_START, 0, 1.1f, f.actor->o.x, f.actor->o.y, f.actor->o.z+0.3f+(sinf(lastmillis/100.0f)+1)/10, lastmillis/2.5f, 0, 120.0f);
  52.             }
  53.             else
  54.             {
  55.                 s_sprintfd(path)("pickups/flags/%s", team_string(e.attr2));
  56.                 rendermodel(path, ANIM_FLAG|ANIM_LOOP, 0, 4, e.x, e.y, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 120.0f);
  57.             }
  58.         }
  59.         else if(isitem(e.type))
  60.         {
  61.             if(OUTBORD(e.x, e.y) || !e.spawned) continue;
  62.             renderent(e, entmdlnames[e.type-I_CLIPS], (float)(1+sinf(lastmillis/100.0f+e.x+e.y)/20), lastmillis/10.0f);
  63.         }
  64.     }
  65. }
  66.  
  67. itemstat itemstats[] =
  68. {
  69.     {1,     1,   1,   S_ITEMAMMO},      //knife dummy
  70.     {16, 32,  72,  S_ITEMAMMO},   //pistol
  71.     {14, 28,  21,  S_ITEMAMMO},   //shotgun
  72.     {60, 90,  90,  S_ITEMAMMO},   //subgun
  73.     {10, 20,  15,  S_ITEMAMMO},   //sniper
  74.     {30, 60,  60,  S_ITEMAMMO},   //assault
  75.     {2,  0,   2,   S_ITEMAMMO},   //grenade
  76.     {33, 100, 100, S_ITEMHEALTH}, //health
  77.     {50, 100, 100, S_ITEMARMOUR}, //armour
  78.     {16, 0,   72,  S_ITEMPUP},    //powerup
  79. };
  80.  
  81. void baseammo(int gun, playerent *d) { d->ammo[gun] = itemstats[gun].add*2; }
  82.  
  83. // these two functions are called when the server acknowledges that you really
  84. // picked up the item (in multiplayer someone may grab it before you).
  85.  
  86. void equipitem(playerent *d, int i, int &v, int t)
  87. {
  88.     itemstat &is = itemstats[t];
  89.     ents[i].spawned = false;
  90.     v += is.add;
  91.     if(v>is.max) v = is.max;
  92.     if(d==player1) playsoundc(is.sound);
  93.     else playsound(is.sound, &d->o);
  94. }
  95.  
  96. void realpickup(int n, playerent *d)
  97. {
  98.     switch(ents[n].type)
  99.     {
  100.         case I_CLIPS:  
  101.             equipitem(d, n, d->ammo[1], 1); 
  102.             break;
  103.         case I_AMMO: 
  104.             equipitem(d, n, d->ammo[d->primary], d->primary); 
  105.             break;
  106.         case I_GRENADE: 
  107.             equipitem(d, n, d->mag[6], 6); 
  108.             player1->thrownademillis = 0;
  109.             break;
  110.         case I_HEALTH:  
  111.             equipitem(d, n, d->health, 7);
  112.             break;
  113.         case I_ARMOUR:
  114.             equipitem(d, n, d->armour, 8);
  115.             break;
  116.         case I_AKIMBO:
  117.             d->akimbomillis = lastmillis+30000;
  118.             d->mag[GUN_PISTOL] = 16;
  119.             equipitem(d, n, d->ammo[1], 9);
  120.             if(d==player1 && d->gunselect!=GUN_SNIPER) weaponswitch(GUN_PISTOL);
  121.             break;
  122.     }
  123. }
  124.  
  125. // these functions are called when the client touches the item
  126.  
  127. void additem(playerent *d, int i, int &v, int spawnsec, int t)
  128. {
  129.     if(v<itemstats[t].max) 
  130.     {
  131.         if(d->type==ENT_PLAYER) addmsg(SV_ITEMPICKUP, "rii", i, spawnsec);
  132.         else if(d->type==ENT_BOT && serverpickup(i, spawnsec, -1)) realpickup(i, d);
  133.         ents[i].spawned = false;
  134.     }
  135. }
  136.  
  137. void pickup(int n, playerent *d)
  138. {
  139.     int np = 1;
  140.     loopv(players) if(players[i]) np++;
  141.     np = np<3 ? 4 : (np>4 ? 2 : 3);         // spawn times are dependent on number of players
  142.     int ammo = np*2;
  143.     switch(ents[n].type)
  144.     {
  145.         case I_CLIPS: 
  146.             additem(d, n, d->ammo[1], ammo, 1);
  147.             break;
  148.         case I_AMMO: 
  149.             additem(d, n, d->ammo[d->primary], ammo, d->primary); 
  150.             break;
  151.         case I_GRENADE: additem(d, n, d->mag[6], ammo, 6); break;
  152.         case I_HEALTH:  additem(d, n, d->health,  np*5, 7); break;
  153.  
  154.         case I_ARMOUR:
  155.             additem(d, n, d->armour, 20, 8);
  156.             break;
  157.  
  158.         case I_AKIMBO:
  159.             additem(d, n, d->akimbo, 60, 9);
  160.             break;
  161.             
  162.         case LADDER:
  163.             d->onladder = true;
  164.             break;
  165.  
  166.         case CTF_FLAG:
  167.         {
  168.             if(d==player1)
  169.             {
  170.                 int flag = ents[n].attr2;
  171.                 flaginfo &f = flaginfos[flag];
  172.                 flaginfo &of = flaginfos[team_opposite(flag)];
  173.                 if(f.state == CTFF_STOLEN) break;
  174.                 
  175.                 if(flag == team_int(d->team)) // its the own flag
  176.                 {
  177.                     if(f.state == CTFF_DROPPED) flagreturn();
  178.                     else if(f.state == CTFF_INBASE && of.state == CTFF_STOLEN && of.actor == d && of.ack) flagscore();
  179.                 }
  180.                 else flagpickup();
  181.             }
  182.             break;
  183.         }
  184.     }
  185. }
  186.  
  187. void checkitems(playerent *d)
  188. {
  189.     if(editmode) return;
  190.     d->onladder = false;
  191.     loopv(ents)
  192.     {
  193.         entity &e = ents[i];
  194.         if(e.type==NOTUSED) continue;
  195.         if(e.type==LADDER)
  196.         {
  197.             if(OUTBORD(e.x, e.y)) continue;
  198.             vec v(e.x, e.y, d->o.z);
  199.             float dist1 = d->o.dist(v);
  200.             float dist2 = d->o.z - (S(e.x, e.y)->floor+d->eyeheight);
  201.             if(dist1<1.5f && dist2<e.attr1) pickup(i, d);
  202.             continue;
  203.         }
  204.         
  205.         if(!e.spawned) continue;
  206.         if(OUTBORD(e.x, e.y)) continue;
  207.         vec v(e.x, e.y, S(e.x, e.y)->floor+d->eyeheight);
  208.         if(d->o.dist(v)<2.5f) pickup(i, d);
  209.     }
  210. }
  211.  
  212. void putitems(ucharbuf &p)            // puts items in network stream and also spawns them locally
  213. {
  214.     loopv(ents) if(isitem(ents[i].type) || ents[i].type==CARROT || (multiplayer(false) && gamespeed!=100 && (i=-1)))
  215.     {
  216.         if(m_noitemsnade && ents[i].type!=I_GRENADE) continue;
  217.         else if(m_pistol && ents[i].type==I_AMMO) continue;
  218.         putint(p, i);
  219.         ents[i].spawned = true;
  220.     }
  221. }
  222.  
  223. void resetspawns() 
  224. {
  225.     loopv(ents) ents[i].spawned = false;
  226.     if(m_noitemsnade || m_pistol)
  227.         loopv(ents)
  228.         {
  229.             entity &e = ents[i];
  230.             if(m_noitemsnade && e.type == I_CLIPS) e.type = I_GRENADE;
  231.             else if(m_pistol && e.type==I_AMMO) e.type = I_CLIPS;
  232.         }
  233. }
  234. void setspawn(int i, bool on) { if(ents.inrange(i)) ents[i].spawned = on; }
  235.  
  236. void equip(playerent *d)
  237. {
  238.     if(m_pistol) d->primary = GUN_PISTOL;
  239.     else if(m_osok) d->primary = GUN_SNIPER;
  240.     else if(m_lss) d->primary = GUN_KNIFE;
  241.     else d->primary = d->nextprimary;
  242.  
  243.     loopi(NUMGUNS) d->ammo[i] = d->mag[i] = 0;
  244.  
  245.     d->mag[GUN_KNIFE] = d->ammo[GUN_KNIFE] = 1;
  246.     d->mag[GUN_GRENADE] = d->ammo[GUN_GRENADE] = 0;
  247.  
  248.     if(!m_nopistol)
  249.     {
  250.         d->ammo[GUN_PISTOL] = itemstats[GUN_PISTOL].max-magsize(GUN_PISTOL);
  251.         d->mag[GUN_PISTOL] = magsize(GUN_PISTOL);
  252.     }
  253.  
  254.     if(!m_noprimary)
  255.     {
  256.         d->ammo[d->primary] = itemstats[d->primary].start-magsize(d->primary);
  257.         d->mag[d->primary] = magsize(d->primary);
  258.     }
  259.  
  260.     if (d->hasarmour)
  261.     {
  262.         if(gamemode==m_arena) d->armour = 100;
  263.     }
  264.  
  265.     d->gunselect = d->primary;
  266. }
  267.  
  268. void item(int num)
  269. {
  270.     switch(num)
  271.     {
  272.         case GUN_SHOTGUN:
  273.         case GUN_SUBGUN:
  274.         case GUN_SNIPER:
  275.         case GUN_ASSAULT:
  276.             player1->nextprimary = num;
  277.             break;
  278.  
  279.         default:
  280.             conoutf("sorry, you can't use that item yet");
  281.             break;
  282.     }
  283. }
  284.  
  285. COMMAND(item,ARG_1INT);
  286.  
  287. // Added by Rick
  288. bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entity bounding box(entity version)
  289. {
  290.     mapmodelinfo &mmi = getmminfo(e->attr2);
  291.     if(!&mmi || !mmi.h) return false;
  292.     
  293.     float lo = (float)(S(e->x, e->y)->floor+mmi.zoff+e->attr3);
  294.     float hi = lo+mmi.h;
  295.     vec v = to, w(e->x, e->y, lo + (fabs(hi-lo)/2.0f)), *p; 
  296.     v.sub(from);
  297.     w.sub(from);
  298.     float c1 = w.dot(v);
  299.  
  300.     if(c1<=0) p = &from;
  301.     else
  302.     {
  303.         float c2 = v.squaredlen();
  304.         if(c2<=c1) p = &to;
  305.         else
  306.         {
  307.             float f = c1/c2;
  308.             v.mul(f);
  309.             v.add(from);
  310.             p = &v;
  311.         }
  312.     }
  313.                         
  314.     if (p->x <= e->x+mmi.rad
  315.         && p->x >= e->x-mmi.rad
  316.         && p->y <= e->y+mmi.rad
  317.         && p->y >= e->y-mmi.rad
  318.         && p->z <= hi
  319.         && p->z >= lo)
  320.      {
  321.           if (end) *end = *p;
  322.           return true;
  323.      }
  324.      return false;
  325. }
  326. // End add by Ricks
  327.  
  328. // flag ent actions done by the local player
  329.  
  330. void flagpickup()
  331. {
  332.     flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
  333.     f.flag->spawned = false;
  334.     f.state = CTFF_STOLEN;
  335.     f.actor = player1; // do this although we don't know if we picked the flag to avoid getting it after a possible respawn
  336.     f.actor_cn = getclientnum();
  337.     f.ack = false;
  338.     addmsg(SV_FLAGPICKUP, "ri", f.team);
  339. }
  340.  
  341. void tryflagdrop(bool reset)
  342. {
  343.     flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
  344.     if(f.state==CTFF_STOLEN && f.actor==player1)
  345.     {
  346.         f.flag->spawned = false;
  347.         f.state = CTFF_DROPPED;
  348.         f.ack = false;
  349.         addmsg(reset ? SV_FLAGRESET : SV_FLAGDROP, "ri", f.team);
  350.     }
  351. }
  352.  
  353. void flagreturn()
  354. {
  355.     flaginfo &f = flaginfos[team_int(player1->team)];
  356.     f.flag->spawned = false;
  357.     f.ack = false;
  358.     addmsg(SV_FLAGRETURN, "ri", f.team);
  359. }
  360.  
  361. void flagscore()
  362. {
  363.     flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
  364.     f.ack = false;
  365.     addmsg(SV_FLAGSCORE, "ri", f.team);
  366. }
  367.  
  368. // flag ent actions from the net
  369.  
  370. void flagstolen(int flag, int action, int act)
  371. {
  372.     playerent *actor = act == getclientnum() ? player1 : getclient(act);
  373.     if(!actor) return;
  374.     flaginfo &f = flaginfos[flag];
  375.     f.actor = actor;
  376.     f.actor_cn = act;
  377.     f.flag->spawned = false;
  378.     f.ack = true;
  379.     flagmsg(flag, action);
  380. }
  381.  
  382. void flagdropped(int flag, int action, short x, short y, short z)
  383. {
  384.     flaginfo &f = flaginfos[flag];
  385.     if(OUTBORD(x, y)) return;
  386.     f.flag->x = x;
  387.     f.flag->y = y;
  388.     f.flag->z = (short)floor(x, y);
  389.     if(f.flag->z < hdr.waterlevel) f.flag->z = (short) hdr.waterlevel;
  390.     f.flag->spawned = true;
  391.     f.ack = true;
  392.     flagmsg(flag, action);
  393. }
  394.  
  395. void flaginbase(int flag, int action, int act)
  396. {
  397.     flaginfo &f = flaginfos[flag];
  398.     playerent *actor = act == getclientnum() ? player1 : getclient(act);
  399.     if(actor) { f.actor = actor; f.actor_cn = act; }
  400.     f.flag->x = (ushort) f.originalpos.x;
  401.     f.flag->y = (ushort) f.originalpos.y;
  402.     f.flag->z = (ushort) f.originalpos.z;
  403.     f.flag->spawned = true;
  404.     f.ack = true;
  405.     flagmsg(flag, action);
  406. }
  407.  
  408.