diff --git a/bot/bot_names.txt b/bot/bot_names.txt new file mode 100644 index 00000000..6fc48440 --- /dev/null +++ b/bot/bot_names.txt @@ -0,0 +1,126 @@ +Killer +Mike +CubeAddict +Supa +Shootme +Coolbot +stefanhendriks +Dude +Dumb +Rabid Newb +Eek +w00t +Pwned +Indoor Terrain +Dumbstruck +[prrt]brainfart +Santa Far +Jacques Chirac +Aristotles +MuHaHaHa +0x0DEFACED +James Bonk +Rotaredom Murof +zaiBan +YHWH +gruiiik gruiiik +Lady Die +!!!BUY NOW!!! +where_am_i +PMB +Leagle Eagle +Me +unnamed +Player +Maleficus +Grolsch +Gambrinius +Staropramen +Carlsberg +Tuborg +Heineken +Amstel +Kilkenny +Kronebourg +Hell +Koff +Orval +Zlatopramen +Lapin Kulta +Kaltenberg +Zeunerts +Bluesman +Stefan +Dumber +XP|TheNameless +todesgurke +trm +Sabre +Oldy +kiki +b00nkind +Spider_Scouter +GDawg +Memed +Whistler +SoUlFaThEr +botmeister +davek +Dave +Siro +MikeJ +Dude +Dodging_Bullet +Tomahawk +Target +Mom +Newbie +Killah +Azrael +Blaster +GrandMa +Robot +CPU +Coward +FragMe +ILikeCheese +Freshmeat +Dragon +Dr00l +Dunno +New_B +L33t_kR3W +Bones +MrJoe +Shrike +Captain Shrimps +Count Draculol +Harun Al-RushIt +Honey Bunny +Joe Blow +Z00per N00b +Corporal Clegg +Rushing Russian +Johnny Crash +Private Parts +Major Headache +General Surgery +luggable +fried circuits +Byte my ASCII! +CPLD +FPGA +THE_STORM +Die Hard +Bad boy +Beast +Dead man +chibby +teh_ownerer +teh_masterer +ThE_MarD +teh_smex +t3h_p@!|\| +KillSwitch +InsertNameHere +Johnny5 diff --git a/bot/bot_skill.cfg b/bot/bot_skill.cfg new file mode 100644 index 00000000..e5dd9596 --- /dev/null +++ b/bot/bot_skill.cfg @@ -0,0 +1,213 @@ +# **Skill File For The Cube Bots** +# +# +# Credits: Shad0w : Description is based on his work. +# +# +# FILE DESCRIPTION: +# +# Lines starting with a # and blank lines will be ignored. In this file you +# can modify the reaction delays and aim speeds used by the bots. If this file +# doesnt exist default settings will be used. +# +# BOT SKILL VARIABLE NOTES: +# +# min_XXX is the minimum amount of time\distance\degrees before a bot will respond +# max_XXX is the maximum amount of time\distance\degrees a bot will respond +# +# +# BOT AIM VARIABLE NOTES: +# +# The offset and the aim speed are more base values. When a bot has to turn little the aimspeed +# and the aim offset will be lower(so he will aim more precise) and when a bot has to turn much +# the aimspeed and aim offset will be higher(so he will aim fast but inaccurate). +# +# +# BOT SKILL VARIABLES: +# +# min_x_aim_offset and +# max_x_aim_offset and +# min_y_aim_offset and +# max_y_aim_offset and +# Description = Sets the aim offset. This is the percentage of the difference between +# the current angle and the ideal angle. x = vertical angle, y = horizontal angle. +# Unit of Measure = Percentage (highest value is 100) +# +# min_x_aim_speed and +# max_x_aim_speed and +# min_y_aim_speed and +# max_y_aim_speed : +# Description = Sets the degrees a bot will turn in one second. x = vertical angle, y = horizontal angle. +# Unit of Measure = Degrees +# +# min_attack_delay and +# max_attack_delay : +# Description = Amount of seconds the bot will wait after he attacks again. +# Unit of Measure = Seconds +# +# min_enemy_search_delay and +# max_enemy_search_delay : +# Description = The time it takes for a bot to find a new enemy once their previous enemy is lost. +# Unit of Measure = Seconds +# +# can_predict_position : +# Description = Sets if the bot will predict their enemy's position. +# Unit of Measure = Bool(1 = on, 0 = off) +# +# can_circle_strafe : +# Description = Sets if the bot will circle strafe around their enemy. +# Unit of Measure = Bool(1 = on, 0 = off) +# +# can_search_items_in_combat : +# Description = Sets if the bot will search for items when he has an enemy. +# Unit of Measure = Bool(1 = on, 0 = off) +# +# can_predict_position : +# Description = Sets if the bot will predict their enemy's position. +# Unit of Measure = Bool(1 = on, 0 = off) +# +# shoot_at_feet_percent +# Description = Sets the percentage the bot will shoot at the enemies feet when using +# a weapon like a rocket launcher. +# Unit of Measure = Percentage (highest value is 100) +# +# max_hear_volume +# Description = Sets 'how much' the bot can hear, how lower the value, how lower the max distance a +# bot can still hear a sound. +# Unit of Measure = Integer (100 is max). +# +# +# SKILL LEVELS: +# +# There are five skill levels to edit (and choose from ingame). SKILL1 is the highest skill level +# while SKILL5 is the lowest skill level. +# +#----------------------------------------------------------------------------------------------- + + +[SKILL1] +min_x_aim_speed 330 +max_x_aim_speed 355 +min_y_aim_speed 350 +max_y_aim_speed 375 + +min_x_aim_offset 15 +max_x_aim_offset 20 +min_y_aim_offset 10 +max_y_aim_offset 15 + +min_attack_delay 0.1 +max_attack_delay 0.4 + +min_enemy_search_delay 0.09 +max_enemy_search_delay 0.12 + +can_predict_position 1 +can_circle_strafe 1 +can_search_items_in_combat 1 + +shoot_at_feet_percent 85 +max_hear_volume 75 + + +[SKILL2] +min_general_delay 0.035 +max_general_delay 0.045 + +min_x_aim_speed 250 +max_x_aim_speed 265 +min_y_aim_speed 260 +max_y_aim_speed 280 + +min_x_aim_offset 20 +max_x_aim_offset 25 +min_y_aim_offset 15 +max_y_aim_offset 20 + +min_attack_delay 0.3 +max_attack_delay 0.6 + +min_enemy_search_delay 0.12 +max_enemy_search_delay 0.17 + +can_predict_position 1 +can_circle_strafe 1 +can_search_items_in_combat 1 + +shoot_at_feet_percent 60 +max_hear_volume 60 + + +[SKILL3] +min_x_aim_speed 190 +max_x_aim_speed 225 +min_y_aim_speed 210 +max_y_aim_speed 240 + +min_x_aim_offset 25 +max_x_aim_offset 30 +min_y_aim_offset 20 +max_y_aim_offset 25 + +min_attack_delay 0.5 +max_attack_delay 1.1 + +min_enemy_search_delay 0.18 +max_enemy_search_delay 0.22 + +can_predict_position 0 +can_circle_strafe 1 +can_search_items_in_combat 0 + +shoot_at_feet_percent 25 +max_hear_volume 40 + + +[SKILL4] +min_x_aim_speed 155 +max_x_aim_speed 170 +min_y_aim_speed 175 +max_y_aim_speed 195 + +min_x_aim_offset 30 +max_x_aim_offset 35 +min_y_aim_offset 25 +max_y_aim_offset 30 + +min_attack_delay 1.2 +max_attack_delay 1.6 + +min_enemy_search_delay 0.25 +max_enemy_search_delay 0.30 + +can_predict_position 0 +can_circle_strafe 0 +can_search_items_in_combat 0 + +shoot_at_feet_percent 10 +max_hear_volume 30 + + +[SKILL5] +min_x_aim_speed 60 +max_x_aim_speed 90 +min_y_aim_speed 80 +max_y_aim_speed 110 + +min_x_aim_offset 35 +max_x_aim_offset 40 +min_y_aim_offset 30 +max_y_aim_offset 35 + +min_attack_delay 1.5 +max_attack_delay 2.0 + +min_enemy_search_delay 0.30 +max_enemy_search_delay 0.36 + +can_predict_position 0 +can_circle_strafe 0 +can_search_items_in_combat 0 + +shoot_at_feet_percent 0 +max_hear_volume 15 diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index 4f736037..db5360bc 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -13,33 +13,44 @@ int range[] = { 40, 5, 8, 4, 4, 4, 3, 3, 12, 11, 17, 11, 13, 19, 6, 9, 4, 5, 6, /*int frame[] = { 178, 184, 190, 137, 183, 189, 197, 164, 46, 51, 54, 32, 0, 0, 40, 1, 154, 162, 67, 168 }; int range[] = { 6, 6, 8, 28, 1, 1, 1, 1, 8, 19, 4, 18, 40, 1, 6, 15, 6, 1, 1, 1 };*/ +VAR(die,0,0,1); + void renderclient(dynent *d, bool team, char *mdlname, float scale) { int n = 3; + int oldaniminterpt = -1; float speed = 100.0f; float mz = d->o.z-d->eyeheight+1.55f*scale; int basetime = -((int)d&0xFFF); if(d->state==CS_DEAD) { - /* d->pitch = 0.1f; + d->pitch = 0.1f; int r; - n = ((int)d%3); + n = (d->lastaction%3)+18; r = range[n]; basetime = d->lastaction; int t = lastmillis-d->lastaction; if(t<0 || t>20000) return; - if(t>(r-1)*100) { n += 3; if(t>(r+10)*100) { t -= (r+10)*100; mz -= t*t/10000000000.0f*t; }; }; - n+=18; - if(mz<-1000) return;*/ + if(t>(r-1)*100-50) + { + n += 3; + if(t>(r+10)*100) + { + t -= (r+10)*100; + mz -= t*t/10000000000.0f*t; + }; + oldaniminterpt = getvar("animationinterpolationtime"); // disable anim interp. temporarly + setvar("animationinterpolationtime", 0); + }; + //if(mz<-1000) return; } else if(d->state==CS_EDITING) { n = 8; } - else if(d->state==CS_LAGGED) { n = 9; } - /*else if(d->monsterstate==M_ATTACKING) { n = 8; } - else if(d->monsterstate==M_PAIN) { n = 10; } */ - else if((!d->move && !d->strafe) || !d->moving) { n = 0; } + else if(d->state==CS_LAGGED) { n = 13; } + else if((!d->move && !d->strafe) /*|| !d->moving*/) { n = 0; } else if(!d->onfloor && d->timeinair>100) { n = 6; } else { n = 1; speed = 1200/d->maxspeed*scale; }; 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, true, d); + if(oldaniminterpt!=-1) setvar("animationinterpolationtime", oldaniminterpt); }; extern int democlientnum; diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index a3f5dc60..562d138d 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -59,7 +59,7 @@ void spawnstate(dynent *d) // reset player state not persistent acc d->gunselect = GUN_PISTOL; d->gunwait = 0; d->attacking = false; - d->lastaction = 0; + d->lastaction = lastmillis; d->weaponchanging = false; if(d==player1) { diff --git a/source/src/cube.h b/source/src/cube.h index 21581d74..1a60dc0a 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -230,6 +230,7 @@ struct dynent // players & monsters md3state animstate[3]; int lastanimswitchtime; md2state current, prev; + int attackmillis; bool onladder; int gravity; @@ -276,6 +277,9 @@ struct physent : dynent // nades, gibs dynent *owner; }; +#define NADE_IN_HAND (player1->gunselect==GUN_GRENADE && player1->inhandnade) +#define NADE_THROWING (player1->gunselect==GUN_GRENADE && player1->thrownademillis && !player1->inhandnade) + #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 diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 4cc3acc5..d99c3b0f 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -133,8 +133,6 @@ void realpickup(int n, dynent *d) break; case I_GRENADE: radditem(n, d->mag[6], 6); - player1->reloading = true; - //player1->lastaction = lastmillis; // fixme player1->thrownademillis = 0; break; case I_HEALTH: diff --git a/source/src/menus.cpp b/source/src/menus.cpp index 2ae0c741..822890c1 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -218,7 +218,7 @@ bool menukey(int code, bool isdown) else if(code==SDLK_UP || code==-4) menusel--; else if(code==SDLK_DOWN || code==-5) menusel++; int n = menus[vmenu].items.length(); - if(menusel<0) menusel = n-1; + if(menusel<0) menusel = n>0 ? n-1 : 0; else if(menusel>=n) menusel = 0; menus[vmenu].menusel = menusel; if(menusel != oldmenusel)execute(menus[vmenu].items[menusel].hoveraction, true); diff --git a/source/src/rendermd2.cpp b/source/src/rendermd2.cpp index bd595954..84a4daf0 100644 --- a/source/src/rendermd2.cpp +++ b/source/src/rendermd2.cpp @@ -159,8 +159,10 @@ void md2::render(vec &light, int frame, int range, float x, float y, float z, fl { if(range==0 || frame+range-1>numFrames) { + conoutf("invalid md2 frame or range!"); return; } + md2state ai; ai.frame = frame; ai.basetime = basetime; @@ -218,6 +220,8 @@ void md2::render(vec &light, int frame, int range, float x, float y, float z, fl aifrac2 = 1-aifrac1; }; + if(doai) printf("(%i %f %i) %f (%i %f %i)\n", prev.fr1, prev.frac1, prev.fr2, aifrac1, current.fr1, current.frac1, current.fr2); + for(int *command = glCommands; (*command)!=0;) { int numVertex = *command++; diff --git a/source/src/rendermd3.cpp b/source/src/rendermd3.cpp index 6dca764b..3348d302 100644 --- a/source/src/rendermd3.cpp +++ b/source/src/rendermd3.cpp @@ -231,6 +231,8 @@ void md3model::render() a->frm = 0; nextfrm = a->frm + 1; } + + /*printf("frame %i\n", a->frm);*/ #define interpolate(p1,p2) ((p1) + t * ((p2) - (p1))) @@ -401,8 +403,7 @@ struct weaponmove calcmove(vec base, int basetime) { bool akimbo = player1->akimbo && player1->gunselect==GUN_PISTOL; - bool throwingnade = player1->gunselect==GUN_GRENADE && player1->thrownademillis && !player1->inhandnade; - int timediff = throwingnade ? (lastmillis-player1->thrownademillis) : lastmillis-basetime; + int timediff = NADE_THROWING ? (lastmillis-player1->thrownademillis) : lastmillis-basetime; int animtime = attackdelay(player1->gunselect); int rtime = reloadtime(player1->gunselect); @@ -446,8 +447,8 @@ struct weaponmove if(player1->lastaction && player1->lastattackgun==player1->gunselect) { - if(throwingnade) anim = MDL_GUN_ATTACK2; - else if(lastmillis-player1->lastactiongunselect==GUN_GRENADE && player1->inhandnade)) + if(NADE_THROWING && timedifflastaction struct vector bool empty() { return ulen==0; }; int length() { return ulen; }; - T &operator[](int i) { assert(i>=0 && iulen){ fatal("fuck"); }; + /*assert(i>=0 && ii; ulen--) buf[ulen-1].~T(); }; T *getbuf() { return buf; }; diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 353eff03..cc7d486c 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -2,7 +2,7 @@ #include "cube.h" -struct guninfo { short sound, reload, reloadtime, attackdelay, damage, projspeed, part, spread, recoil, magsize, mdl_kick_rot, mdl_kick_back; char *name; }; +struct guninfo { short sound, reload, reloadtime, attackdelay, damage, projspeed, part, spread, recoil, magsize, mdl_kick_rot, mdl_kick_back; bool isauto; char *name; }; const int SGRAYS = 20; //down from 20 (default) const float SGSPREAD = 2; @@ -11,12 +11,12 @@ vec sg[SGRAYS]; //change the particales guninfo guns[NUMGUNS] = { - { S_KNIFE, S_NULL, 0, 500, 50, 0, 0, 1, 1, 1, 0, 0, "knife" }, - { S_PISTOL, S_RPISTOL, 1400, 170, 20, 0, 0, 80, 10, 8, 6, 5, "pistol" }, // *SGRAYS - { S_SHOTGUN, S_RSHOTGUN, 2400, 1000, 6, 0, 0, 1, 35, 7, 9, 9, "shotgun" }, //reload time is for 1 shell from 7 too powerful to 6 - { S_SUBGUN, S_RSUBGUN, 1650, 80, 17, 0, 0, 70, 15, 30, 1, 2, "subgun" }, - { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, 4, 4, "sniper" }, - { S_ASSULT, S_RASSULT, 2000, 130, 20, 0, 0, 20, 40, 20, 0, 2, "assult" }, //recoil was 44 + { S_KNIFE, S_NULL, 0, 500, 50, 0, 0, 1, 1, 1, 0, 0, false, "knife" }, + { S_PISTOL, S_RPISTOL, 1400, 170, 20, 0, 0, 80, 10, 8, 6, 5, false, "pistol" }, // *SGRAYS + { S_SHOTGUN, S_RSHOTGUN, 2400, 1000, 6, 0, 0, 1, 35, 7, 9, 9, false, "shotgun" }, //reload time is for 1 shell from 7 too powerful to 6 + { S_SUBGUN, S_RSUBGUN, 1650, 80, 17, 0, 0, 70, 15, 30, 1, 2, true, "subgun" }, + { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, 4, 4, false, "sniper" }, + { S_ASSULT, S_RASSULT, 2000, 130, 20, 0, 0, 20, 40, 20, 0, 2, true, "assult" }, //recoil was 44 { S_NULL, S_NULL, 1000, 1200, 150, 20, 6, 1, 1, 1, 3, 1, "grenade" }, }; @@ -25,21 +25,8 @@ bool gun_changed = false; void checkweaponswitch() { + if(!player1->weaponchanging) return; int timeprogress = lastmillis-player1->lastaction; - - // exception: nade. after throwing a nade, switch to a new one or to the primary - if(player1->gunselect==GUN_GRENADE && player1->thrownademillis && - timeprogress >= 520 && player1->lastaction && player1->lastattackgun==player1->gunselect) - { - player1->weaponchanging = true; - player1->nextweapon = player1->mag[GUN_GRENADE] ? GUN_GRENADE : player1->primary; - player1->thrownademillis = 0; - player1->lastaction = lastmillis-1-WEAPONCHANGE_TIME/2; - timeprogress = lastmillis-player1->lastaction; - }; - - if(!player1->weaponchanging) return; - if(timeprogress>WEAPONCHANGE_TIME) { player1->weaponchanging = false; player1->lastaction = 0; } else if(timeprogress>WEAPONCHANGE_TIME/2) { @@ -103,7 +90,7 @@ COMMAND(altattack, ARG_NONE); void reload(dynent *d) { - if(!d) return; + if(!d || d->reloading) return; if(scoped) togglescope(); bool akimbo = d->gunselect==GUN_PISTOL && d->akimbo!=0; @@ -111,7 +98,6 @@ void reload(dynent *d) if(akimbo && d->mag[d->gunselect]>=(guns[d->gunselect].magsize * 2)) return; else if(d->mag[d->gunselect]>=guns[d->gunselect].magsize && d->akimbo==0) return; if(d->ammo[d->gunselect]<=0) return; - if(d->reloading) return; d->reloading = true; d->lastaction = lastmillis; @@ -562,7 +548,7 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nadepercent) break; case GUN_GRENADE: - { + { if(d!=player1) { int nademillis = nadetimer/100*nadepercent; @@ -570,7 +556,7 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nadepercent) physent *p = new_nade(d, nademillis); throw_nade(d, to, p); } - } + }; break; case GUN_SNIPER: @@ -603,7 +589,7 @@ void raydamage(dynent *o, vec &from, vec &to, dynent *d, int i) else if(intersect(o, from, to)) hitpush(i, qdam, o, d, from, to); }; -void spreadandrecoil(vec & from, vec & to, dynent * d) +void spreadandrecoil(vec &from, vec &to, dynent *d) { //nothing special for a knife if (d->gunselect==GUN_KNIFE || d->gunselect==GUN_GRENADE) return; @@ -645,104 +631,122 @@ void spreadandrecoil(vec & from, vec & to, dynent * d) if(d->pitch<80.0f) d->pitch += guns[d->gunselect].recoil*0.05f; }; +bool hasammo(dynent *d) // bot mod +{ + if(!d->mag[d->gunselect]) + { + if (d->bIsBot) botplaysound(S_NOAMMO, d); + else playsoundc(S_NOAMMO); + d->gunwait = 250; + d->lastattackgun = -1; + printf("noammo\n"); + return false; + } else { printf("ammo\n"); return true; } +} const int grenadepulltime = 650; - bool akimboside = false; void shoot(dynent *d, vec &targ) { - if(d->weaponchanging) return; - int attacktime = lastmillis-d->lastaction; - if(d->gunselect==GUN_GRENADE && d->inhandnade && !d->attacking) // throw nade - { - if(attacktime>grenadepulltime) throw_nade(d, targ, d->inhandnade); - return; - }; - - if(attacktimegunwait) return; - d->gunwait = 0; - d->reloading = false; + int attacktime = lastmillis-d->lastaction; + if(d->weaponchanging || attacktimegunwait) return; + d->gunwait = 0; - if(!d->attacking) - { - d->shots = 0; - return; - }; - - if(d->gunselect!=GUN_SUBGUN && d->gunselect!=GUN_ASSULT && d->gunselect!=GUN_GRENADE) d->attacking = false; //makes sub/assult autos - else d->shots++; + if(d->gunselect==GUN_GRENADE) + { + d->shots = 0; - if(d->gunselect==GUN_PISTOL && d->akimbo) - { - d->attacking = true; //make akimbo auto - d->akimbolastaction[akimboside?1:0] = lastmillis; - akimboside = !akimboside; - } - - d->lastaction = lastmillis; - d->lastattackgun = d->gunselect; - //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) d->mag[d->gunselect]--; + if(d->thrownademillis && attacktime >= 13*(1000/25)) + { + d->weaponchanging = true; + d->nextweapon = d->mag[GUN_GRENADE] ? GUN_GRENADE : d->primary; + d->thrownademillis = 0;// + d->lastaction = lastmillis-1-WEAPONCHANGE_TIME/2; + }; - vec from = d->o; - vec to = targ; - from.z -= 0.2f; // below eye - - spreadandrecoil(from,to,d); + if(d->attacking && !d->inhandnade) // activate + { + if(!hasammo(d)) return; + d->mag[d->gunselect]--; + new_nade(d); + d->gunwait = guns[d->gunselect].attackdelay; + d->lastaction = lastmillis; + d->reloading = false; + return; + } + else if(d->inhandnade) // throw nade + { + if(attacktime>grenadepulltime) throw_nade(d, targ, d->inhandnade); + return; + } + } + else + { + if(!d->attacking) return; + d->lastaction = lastmillis; + d->lastattackgun = d->gunselect; - vdist(dist, unitv, from, to); - vdiv(unitv, dist); + if(!hasammo(d)) { d->shots = 0; return; }; + d->reloading = false; + + + if(guns[d->gunselect].isauto) d->shots++; + else d->attacking = false; - if(d->gunselect==GUN_KNIFE) - { - vmul(unitv, 3); // punch range - to = from; - vadd(to, unitv); - }; - if(d->gunselect==GUN_SHOTGUN) createrays(from, to); - - if(d->gunselect==GUN_PISTOL && d->akimbo) d->gunwait = guns[d->gunselect].attackdelay / 2; //make akimbo pistols shoot twice as fast as normal pistol - else d->gunwait = guns[d->gunselect].attackdelay; - - if(d->gunselect==GUN_GRENADE) // activate - { - if(!d->inhandnade) new_nade(d); - else d->mag[d->gunselect]++; - return; - } - -//fixmebot - shootv(d->gunselect, from, to, d, 0); - 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), 0 ); + if(d->gunselect==GUN_PISTOL && d->akimbo) + { + d->attacking = true; //make akimbo auto + d->akimbolastaction[akimboside?1:0] = lastmillis; + akimboside = !akimboside; + } + + if(d->gunselect) d->mag[d->gunselect]--; - if(guns[d->gunselect].projspeed) return; - - loopv(players) - { - dynent *o = players[i]; - if(!o) continue; - 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 - - if(d->bIsBot) raydamage(player1, from, to, d, -1); + } + + vec from = d->o; + vec to = targ; + from.z -= 0.2f; // below eye + + spreadandrecoil(from,to,d); + vdist(dist, unitv, from, to); + vdiv(unitv, dist); + + if(d->gunselect==GUN_KNIFE) + { + vmul(unitv, 3); // punch range + to = from; + vadd(to, unitv); + }; + if(d->gunselect==GUN_SHOTGUN) createrays(from, to); + + if(d->gunselect==GUN_PISTOL && d->akimbo) d->gunwait = guns[d->gunselect].attackdelay / 2; //make akimbo pistols shoot twice as fast as normal pistol + else d->gunwait = guns[d->gunselect].attackdelay; + + + //fixmebot + shootv(d->gunselect, from, to, d, 0); + 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), 0 ); + + if(guns[d->gunselect].projspeed) return; + + loopv(players) + { + dynent *o = players[i]; + if(!o) continue; + 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 + + if(d->bIsBot) raydamage(player1, from, to, d, -1); + };