/* ----------------------------------------------- GTASC - GTA adaptation for TI Calculators ----------------------------------------------- Programmed by : Olivier SANGALA Version : 1.2 License : Free under GNU General Public License ( see "gpl.txt" ) Release Date : 05/01/2007 Platform : TI89/TI92+/V200 Website : http://olivier.sangala.free.fr Email : olivier_sangala@hotmail.com ---------- License ---------- Copyright (C) 2002-2007 Olivier SANGALA This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //----------------------------------------------------------------------------- /* vehicles functions */ #include // Include All Header Files #include "defines.h" //--------------------------------------------------------------------------- extern TGame*Game; //--------------------------------------------------------------------------- void Veh_Init(TVeh*V) { memset(V,0,sizeof(TVeh)); V->health=VEH_HEALTH; Veh_OnNewAngle(V); Veh_LoadTD(V); } //--------------------------------------------------------------------------- // veh computer control function void Veh_CC(TVeh*V) { int b=V->CC_behaviour; // BH_None if (b==BH_Veh_None) { V->MD.speed=0; } // BH_Veh_Computer else if (b==BH_Veh_Computer) { Veh_CC_Computer(V); } // others else { // cancel any chase behavior if ff=0 if (Game->Save.fugitive_factor==0) { V->CC_behaviour=BH_Veh_None; return; } // BH_Veh_HurtChase TPed*P2=Game->MainPed; int dx = P2->MD.Pos.x-V->MD.Pos.x; int dy = P2->MD.Pos.y-V->MD.Pos.y; int too_close = (abs(dx)<32 && abs(dy)<32); V->MD.angle = GetFastAngle16(V->MD.Pos,P2->MD.Pos); V->MD.speed = 2*SPEED_LCD; if (too_close) V->MD.speed=0; } } //--------------------------------------------------------------------------- // veh default behaviour void Veh_CC_Computer(TVeh*V) { // flag_collideCC if (V->flag_collideCC) { V->flag_collideCC=0; V->CC_flag_stopdelay=3; V->MD.speed=0; return; } // CC_flag_stopdelay if (V->CC_flag_stopdelay) { V->MD.speed=0; return; } // collision with others vehicles TVeh*V2=Game->Vehs; int a=0; for (a=0;aenable) { int dx=V2->MD.Pos.x-V->MD.Pos.x; int dy=V2->MD.Pos.y-V->MD.Pos.y; int angle=V->MD.angle; int angle2=V2->MD.angle; // minimum forward distance = 32 if ( (angle==0 && abs(dx)<16 && dy<0 && dy>-32) || (angle==8 && abs(dx)<16 && dy>0 && dy<32) || (angle==4 && abs(dy)<16 && dx>0 && dx<32) || (angle==12 && abs(dy)<16 && dx<0 && dx>-32)) { V->MD.speed=0; return; } // priority to vehicles coming from right // not implemented = not really useful } int rx = REM16(V->MD.Pos.x); int ry = REM16(V->MD.Pos.y); byte xx = QUOT16(V->MD.Pos.x); byte yy = QUOT16(V->MD.Pos.y); int turn_list[4]; int turn_count=0; byte tiles_way[8]={12,4,8,0,12,4,8,0}; // if exactly on tile if (rx==0 && ry==0) { // if not on crossroads if ((*GET_PTR(xx,yy))!=TILE_CROSSROADS) { byte qx=xx; byte qy=yy; // get tile toward veh if (V->MD.angle==0) qy--; else if (V->MD.angle==4) qx++; else if (V->MD.angle==8) qy++; else if (V->MD.angle==12) qx--; byte tn=(*GET_PTR(qx,qy)); // if border to crossroads if (tn==TILE_CROSSROADS) { // get list of possible directions byte sx=qx; byte sy=qy; if (V->MD.angle!=8) // up { sx=qx;sy=qy; while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sy--; byte t=(*GET_PTR(sx,sy)); if (tMD.angle!=0) // down { sx=qx;sy=qy; while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sy++; byte t=(*GET_PTR(sx,sy)); if (tMD.angle!=4) // left { sx=qx;sy=qy; while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sx--; byte t=(*GET_PTR(sx,sy)); if (tMD.angle!=12) // right { sx=qx;sy=qy; while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sx++; byte t=(*GET_PTR(sx,sy)); if (tCC_angle_turn = turn_list[random(turn_count)]; // keep driving V->MD.speed=SPEED_LCD; } // if border to obstacle else if (!ISTILE_STREET(tn)) { // turn left V->MD.angle-=4; V->MD.angle&=15; // stop driving V->MD.speed=0; } else { // keep driving V->MD.speed=SPEED_LCD; } } // if on crossroads else { if (V->MD.angle!=V->CC_angle_turn) { // check if way is enable byte sx=xx; byte sy=yy; int turn=0; if (V->CC_angle_turn==0) // up { while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sy--; byte t=(*GET_PTR(sx,sy)); if (tCC_angle_turn==8) // down { while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sy++; byte t=(*GET_PTR(sx,sy)); if (tCC_angle_turn==12) // left { while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sx--; byte t=(*GET_PTR(sx,sy)); if (tCC_angle_turn==4) // right { while ((*GET_PTR(sx,sy)==TILE_CROSSROADS)) sx++; byte t=(*GET_PTR(sx,sy)); if (tMD.angle=V->CC_angle_turn; // stop driving V->MD.speed=0; } } else { // keep driving V->MD.speed=SPEED_LCD; } } } // if not exactly on tile else { // keep driving V->MD.speed=SPEED_LCD; } } //--------------------------------------------------------------------------- void Veh_OnNewAngle(TVeh*V) { MD_OnNewAngle(&V->MD); } //--------------------------------------------------------------------------- void Veh_LoadTD(TVeh*V) { int tn=MUL16(V->skin)+V->MD.angle; V->TileData=Game->VP_Veh+MUL32(tn); // make collide tiledata // collide data = plane0 | plane1 unsigned short*ptr = V->TileData2; unsigned short*ptr1 = V->TileData; unsigned short*ptr2 = ptr1+16; int a; for (a=0;a<16;a++) (*ptr++)=((*ptr1++)|(*ptr2++)); } //--------------------------------------------------------------------------- void Veh_GoInto(void) { TVeh*V=Game->MainVeh2; TPed*P=Game->MainPed; // - veh exists if (!V) return; // if !health if (!V->health) return; // - veh stopped if (V->MD.speed) return; // - not police car if (V->skin==VEH_SKIN_COP) return; // - ped & veh ARE close int dx=((V->MD.Pos.x+8)-(P->MD.Pos.x+4)); int dy=((V->MD.Pos.y+8)-(P->MD.Pos.y+4)); if (!(abs(dx)<16 && abs(dy)<16)) return; // --> OK // if computer controlled // - disable computer control // - STATS -> hijacked vehs if (V->CC_behaviour!=BH_Veh_None) { V->CC_behaviour=BH_Veh_None; Game->Save.vehs_hijacked++; } // go into veh Game->motion_type=MT_VEH; Game->MainVeh=V; Game->MainVeh2 = NULL; // MISSIONS FLAGS Game->Miss.flag_vehinto=1; Game->Miss.IntoVeh=V; } //--------------------------------------------------------------------------- void Veh_GetOut(void) { TPed*P=Game->MainPed; TVeh*V=Game->MainVeh; // - veh stopped if (V->MD.speed) return; // get out of veh P->MD.speed = 0; Game->motion_type=MT_PED; Game->MainVeh=NULL; Game->MainVeh2=NULL; // place ped P->MD.Pos=V->MD.Pos; P->MD.Pos.x+=4; P->MD.Pos.y-=8; P->MD.angle=0; Ped_OnNewAngle(P); // test collision int c=TC_Ped_VehOut(P); if (c) { // go back into veh Game->motion_type=MT_VEH; Game->MainVeh=V; Game->MainVeh2 = NULL; } } //--------------------------------------------------------------------------- int VehWay_IsDeadEnd(byte x, byte y, int way) { /* int xx=x; int yy=y; if (way==WAY_L) while((*GET_PTR(xx,yy))<8) xx--; else if (way==WAY_R) while((*GET_PTR(xx,yy))<8) xx++; else if (way==WAY_U) while((*GET_PTR(xx,yy))<8) yy--; else if (way==WAY_D) while((*GET_PTR(xx,yy))<8) yy++; return ((*GET_PTR(xx,yy))!=8); */ return 0; } //--------------------------------------------------------------------------- void Veh_Hurt(TVeh*V, int damage) { // do nothing if veh is gonna blow (h=1) OR is blown (h=0) if (V->health<=1) return; // else decrease health V->health-=damage; if (V->health<1) V->health=1; } //--------------------------------------------------------------------------- void Veh_Blow(TVeh*V) { // debug //return; // do nothing if already blown up if (V->health==0) return; // blow up veh V->health=0; // stop moving V->MD.speed=0; // - disable computer control V->CC_behaviour=BH_Veh_None; // MISSIONS FLAGS Game->Miss.flag_vehblownup=1; Game->Miss.BlownUpVeh=V; // STATS Game->Save.vehs_blown++; // peds into veh die if (V==Game->MainVeh) Ped_Kill(Game->MainPed); // fugitive_factor Game->ff_blownveh++; if (Game->ff_blownveh>=1) { Game->ff_blownveh=0; if (Game->Save.fugitive_factor<4) Game->Save.fugitive_factor++; } // ShakeCamera Game->flag_shake=1; } //--------------------------------------------------------------------------- // tests if main veh is in garage tile (x,y) int VehInGarage(byte y, byte x) { if (Game->motion_type!=MT_VEH) return 0; if (Game->MainVeh->MD.speed!=0) return 0; int vx=Game->MainVeh->MD.Pos.x; int vy=Game->MainVeh->MD.Pos.y; int gx=MUL16(x); int gy=MUL16(y); int r = (abs(vx-gx)<16 && abs(vy-gy)<16); return r; } //---------------------------------------------------------------------------