Post by Chavez on Aug 25, 2009 7:53:09 GMT -8
This is advanced script provided to me by Luke and Andy from the former Indiglow website...i am hoping you may be able to get it working in your maps...I did get this working quite a while ago, but it has been such a long time, that i have forgotten...Also, i do not have VC2, or the VC2 editor installed to figure it out again...so here are the scripts...
level.c script for VC2 "grouping AI" attack
Shigors library.cxx for "grouping AI" attack
VC_Officer_01 (which the group_01 AI will follow into battle)...this can be modified for a second officer by changing group and member ID (i think)...has to be tested by YOU...(dont forget to also alter the script for the second soldier group as well...
And finally the VC squad...The VC squad must match the group number of the officer...They will follow this officer into battle and they will all fight while grouped together until they all die while fighting grouped together...
**Important**, i believe you have to utilize script helpers with this script...If you look into the library.cxx file there are helpers listed as (s_sphere or sph, c_BoxOriented or box, s_SC_Area or area)...the group AI will go to these spheres, boxes, and areas just like they utilize waypoints...I forgot how to make the box, but i believe this is their ultimate goal is to guard the box...and they utilize the spheres to get there...the area is aound those two helpers...damn it has been a while!
Don't forget what i said above about me not having the VC2 game installed, and also the VC2 editor and tools installed...this has to be messed with by YOU or someone else which may know how to implement it...
Good Luck!
Rick (Chavez_US)
level.c script for VC2 "grouping AI" attack
//level.c script for VC2 grouping VC attack
#include <inc\sc_global.h>
#include <..\..\levels\wasteland\data\wasteland_mp\scripts\library.cxx>
int ScriptMain(s_SC_L_info *info){
switch(info->message){
case SC_LEV_MSG_GROUPMAINTASK_FINISHED:
//info->param1 is side, info->param2 is group, coop id is param3
//switch based on the coop id
switch (info->param3){
case 1:
G_MoveToHelper(1,0,"target_02",2);
break;
case 2:
G_MoveToHelper(1,0,"target_03",3);
break;
case 3:
//back to another one
G_MoveToHelper(1,0,"target_04",4);
break;
case 4:
G_MoveToHelper(1,0,"target_03",3);
break;
}
}
return 1;
}
Shigors library.cxx for "grouping AI" attack
//shigors library include file for "grouping AI" attack
#ifndef SHIGOR_LIBRARY_H
#define SHIGOR_LIBRARY_H
#include <inc/sc_global.h>
#include <inc/sc_def.h>
//macros
#define GetLevelPhase SC_ggi(SGI_LEVELPHASE)
#define MISSION_FAILED SC_MissionEnd(SC_MISSIONEND_TYPE_FAILED)
#define MISSION_FINISHED SC_MissionEnd(SC_MISSIONEND_TYPE_FINISHED)
#define MISSION_DONEFADE SC_MissionEnd(SC_MISSIONEND_TYPE_DONE_FADE)
#define MISSION_DONE SC_MissionEnd(SC_MISSIONEND_TYPE_DONE_IMMEDIATELY)
void MISSION_END(char *binkname){
s_SC_MissionEnd missdata;
CLEAR(missdata);
sprintf(missdata.success_bink,binkname);
missdata.type=SC_MISSIONEND_TYPE_FINISHED;
SC_MissionEndEx(&missdata);
}
void MISSION_FAILDEAD(sc_player deadplayer){
s_SC_MissionEnd missdata;
CLEAR(missdata);
missdata.failed_watch_pl=deadplayer;
missdata.type=SC_MISSIONEND_TYPE_FAILED;
SC_MissionEndEx(&missdata);
}
//adds player detector
dword AddDetector(sc_player player, char *helper, dword identifier){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
return SC_PlDet_Create(player,&area,identifier);
}
//adds player detector
dword PC_AddDetector(char *helper, dword identifier){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
return SC_PlDet_Create(SC_PC_Get(),&area,identifier);
}
//group functions
//returns number of the living AI in the group
int GetGroupCount(int side, int group){
sc_player list[64];
CLEAR(list);
return SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY);
}
//returns TRUE if all players in the group are dead
BOOL IsGroupDead(int side, int group){
sc_player list[64];
CLEAR(list);
if (SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY)) return FALSE;
return TRUE;
}
//derespawns all players in the selected group
void DeRespawnGroup(int side, int group){
sc_player list[64];
int num;
int i;
CLEAR(list);
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY);
if (!num) return;
for (i=0;i<num;i++){
SC_P_Derespawn(list[i]);
}
}
//derespawn all AI players in the selected group
void DeRespawnAIGroup(int side, int group){
sc_player list[64];
int num;
int i;
CLEAR(list);
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++){
SC_P_Derespawn(list[i]);
}
}
BOOL Pos_InHelper(c_Vector3 *pos, char *helpername){
s_sphere sph;
c_BoxOriented box;
s_SC_Area area;
CLEAR(area);
switch (SC_GetScriptHelper(helpername,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
return SC_Area_IsPointInside(&area,pos);
}
//returns true if player in helper
BOOL P_InHelper(sc_player player, char *helpername){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
int count, i;
CLEAR(area);
switch (SC_GetScriptHelper(helpername,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
count =SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY , &area);
for (i=0;i<count;i++)
if (list[i]==player) return TRUE;
return FALSE;
}
//returns true if PC is in the selected helper object
BOOL PC_InHelper(char *helpername){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
CLEAR(area);
switch (SC_GetScriptHelper(helpername,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
if (SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_PC_ONLY , &area)) return TRUE;
return FALSE;
}
//returns true if PC is in the selected area
BOOL PC_InArea(s_SC_Area *area){
sc_player list[32];
if (SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_PC_ONLY , area)) return TRUE;
return FALSE;
}
//returns TRUE if there is no one living in the area
BOOL AreaClear(s_SC_Area *area){
sc_player list[32];
if (SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_ALIVEONLY, area)) return FALSE;
return TRUE;
}
//returns TRUE if there is no one living in the helper
BOOL HelperClear(char *helpername){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
CLEAR(area);
switch (SC_GetScriptHelper(helpername,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
if (SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_ALIVEONLY, &area)) return FALSE;
return TRUE;
}
//returns TRUE if there is no one living of the specified side in the helper
BOOL HelperClear2(char *helpername, int side){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[32];
dword count;
int i;
CLEAR(area);
switch (SC_GetScriptHelper(helpername,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return FALSE;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
if (SC_EnumPlayersArea(side, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_ALIVEONLY, &area)) return FALSE;
return TRUE;
}
//returns true if player of selected side, group, memberid is dead
BOOL P_IsDead(int side, int group, int member){
s_SC_P_status status;
sc_player pl;
pl=SC_P_Get(side, group, member);
if (!pl) {
SC_Log(2,"Player %d %d %d not respawned!",side, group, member);
return TRUE;
}
SC_P_GetStatus (pl, &status);
if (status.hp<=0) return TRUE;
return FALSE;
}
//returns true if player is dead
BOOL P_IsDead(sc_player pl){
s_SC_P_status status;
if (!pl)
return TRUE;
SC_P_GetStatus (pl, &status);
if (status.hp<=0) return TRUE;
return FALSE;
}
//returns pointer to the vector plpos, fills it with the position of the selected player
c_Vector3 *P_GetPos(sc_player plid, c_Vector3 *plpos){
s_SC_P_status status;
SC_P_GetStatus(plid, &status);
*plpos = status.pos;
return plpos;
}
float P_GetRot(sc_player plid){
s_SC_P_status status;
SC_P_GetStatus(plid, &status);
return status.rz;
}
//returns pointer to the vector plpos, fills it with the position of the PC
c_Vector3 *PC_GetPos(c_Vector3 *plpos){
s_SC_P_status status;
SC_P_GetStatus(SC_PC_Get(), &status);
*plpos = status.pos;
return plpos;
}
//tell all members in the group about enemy
void GroupUpdateEnemy(int side, int group, sc_player plid){
sc_player list[64];
int num;
int i;
CLEAR(list);
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++){
SC_P_Ai_Situation_UpdateEnemy(list[i],plid);
}
}
//releases maintask for the selected player
void P_ReleaseMainTask(sc_player plid){
s_SC_P_Ai_MainTask maintask;
CLEAR(maintask);
SC_P_Ai_SetMainTask(plid, &maintask);
}
//releases maintask for the selected group
void G_ReleaseMainTask(int side, int group){
s_SC_P_Ai_MainTask maintask;
sc_player list[64];
int num;
int i;
CLEAR(list);
CLEAR(maintask);
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++){
SC_P_Ai_SetMainTask(list[i], &maintask);
}
}
//sets main task for the player to guard area permanently
void P_GuardArea(sc_player plid, s_SC_Area *area, dword coopid){
s_SC_P_Ai_MainTask mt;
CLEAR(mt);
if (!SC_GetRndHideout(area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for player %d in the area",plid);
}
mt.cooperation_id = coopid;
mt.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.target_pl = 0;
mt.target_area = area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 0;
mt.min_enemy_dist = 5;
mt.max_enemy_dist = 10;
SC_P_Ai_SetMainTask(plid, &mt);
}
//sets main task for the group to guard area permanently
void G_GuardArea(int side, int group, s_SC_Area *area, dword coopid){
s_SC_P_Ai_MainTask mt;
sc_player list[64];
int num;
int i;
CLEAR(mt);
CLEAR(list);
mt.cooperation_id = coopid;
mt.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.target_pl = 0;
mt.target_area = area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 0;
mt.min_enemy_dist = 5;
mt.max_enemy_dist = 10;
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++) {
if (!SC_GetRndHideout(area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for side %d group %d in the area",side, group);
}
SC_P_Ai_SetMainTask(list[i], &mt);
}
}
//sets main task for the player to guard helper permanently
void P_GuardHelper(sc_player plid, char *helper, dword coopid){
s_SC_P_Ai_MainTask mt;
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
CLEAR(mt);
if (!SC_GetRndHideout(&area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for player %d, helpername %s",plid,helper);
}
mt.cooperation_id = coopid;
mt.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.target_pl = 0;
mt.target_area = &area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 0;
mt.min_enemy_dist = 5;
mt.max_enemy_dist = 10;
SC_P_Ai_SetMainTask(plid, &mt);
}
//sets main task for player to move to the helper area, after reaching position coopid is sent
void P_MoveToHelper(sc_player plid, char *helper, dword coopid){
s_SC_P_Ai_MainTask mt;
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
CLEAR(mt);
if (!SC_GetRndHideout(&area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for player %d, helpername %s",plid,helper);
}
mt.cooperation_id = coopid;
// mt.flags = SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.flags = SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_MOVINGONPOSITION |
SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_TELLINGTOMOVE;// | SC_P_AI_MAINTASK_FL_NOMOVE_INBATTLE;
mt.target_pl = 0;
mt.target_area = &area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 50;
mt.min_enemy_dist = 5;
mt.max_enemy_dist = 15;
mt.move_step = 15;
SC_P_Ai_SetMainTask(plid, &mt);
}
//sets main task for grou to move to the helper area, after reaching position coopid is sent
void G_MoveToHelper(dword side, dword group, char *helper, dword coopid){
s_SC_P_Ai_MainTask mt;
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
sc_player list[64];
int num;
int i;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
CLEAR(mt);
mt.cooperation_id = coopid;
// mt.flags = SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.flags = SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_MOVINGONPOSITION |
SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_TELLINGTOMOVE;// | SC_P_AI_MAINTASK_FL_NOMOVE_INBATTLE;
mt.target_pl = 0;
mt.target_area = &area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 0;
mt.min_enemy_dist = 10;
mt.max_enemy_dist = 20;
mt.move_step = 20;
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++) {
if (!SC_GetRndHideout(&area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for side %d group %d in the area, helpername %s",side, group, helper);
}
SC_P_Ai_SetMainTask(list[i], &mt);
}
}
//sets main task for the group to guard helper permanently
void G_GuardHelper(int side, int group, char *helper, dword coopid){
s_SC_P_Ai_MainTask mt;
sc_player list[64];
int num;
int i;
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
CLEAR(mt);
CLEAR(list);
mt.cooperation_id = coopid;
mt.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
mt.target_pl = 0;
mt.target_area = &area;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.last_perc_in_group_moves = 0;
mt.min_enemy_dist = 5;
mt.max_enemy_dist = 10;
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++) {
if (!SC_GetRndHideout(&area, SC_GETHIDEOUT_FL_EMPTYONLY, &mt.target)){
SC_message("SHIGOR: Error, hideout not found for side %d group %d in the area, helpername %s",side, group, helper);
}
SC_P_Ai_SetMainTask(list[i], &mt);
}
}
//return TRUE, if player's body can be seen on PC screen
BOOL P_IsVisible(sc_player plid){
s_sphere sph;
s_SC_P_status status;
SC_P_GetStatus(plid, &status);
sph.pos=status.pos;
sph.rad=2;
return SC_SphereIsVisible(&sph);
}
//disables shooting
void PC_DisableShooting(){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.weapons=FALSE;
SC_PC_SetControl(&control);
}
void PC_EnableShooting(){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.weapons=TRUE;
SC_PC_SetControl(&control);
}
void PC_ClearGuns(){
}
//disables player moving, weapon change and interaction
void PC_DisableMove(){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.movement=FALSE;
control.interaction=FALSE;
control.phasechange=FALSE;
control.weapons=FALSE;
control.looking=TRUE;
SC_PC_SetControl(&control);
}
void PC_EnableMove(){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.movement=TRUE;
control.interaction=TRUE;
control.phasechange=TRUE;
control.weapons=TRUE;
control.looking=TRUE;
SC_PC_SetControl(&control);
}
void PC_EnableMWP(BOOL stat){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.use_mwp=stat;
SC_PC_SetControl(&control);
}
void PC_EnableVehicle(BOOL stat){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.enter_vehicle=stat;
SC_PC_SetControl(&control);
}
void PC_SetLeaveVehicle(BOOL stat){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.leave_vehicle=stat;
control.swap_vehicle=stat;
SC_PC_SetControl(&control);
}
//enables all PC controls
void PC_EnableControls(){
s_SC_PC_Control control;
SC_PC_FillControlAllOn(&control);
SC_PC_SetControl(&control);
}
//player will move to hideout on specified helper (use small helpers), valid for peace and script
void P_MoveTo(sc_player plid, char *hideoutname, dword callback){
s_SC_Area area;
s_sphere sph;
c_BoxOriented box;
c_Vector3 target;
dword hideout;
CLEAR(area);
area.sphs=1;
area.sph=&sph;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,hideoutname),&sph.pos);
sph.rad=1;
hideout=SC_GetRndHideout(&area, SC_GETHIDEOUT_FL_EMPTYONLY, &target);
if (!hideout) SC_message("Hideout %s not found",hideoutname);
SC_P_Ai_MoveAt(plid,&target,hideout,callback);
}
//resets AI walk mode
void P_ResetWalkMode(sc_player plid){
SC_P_SetMoveSpeed(plid, 0, SC_P_MOVESPEED_STYLE_RUN, 0);
SC_P_SetSystemAnim(plid, 'X', 30, NULL);
SC_P_SetSystemAnim(plid, 'X', 34, NULL);
SC_P_SetSystemAnim(plid, 'X', 37, NULL);
SC_P_SetSystemAnim(plid, 'X', 70, NULL);
SC_P_SetSystemAnim(plid, 'X', 132, NULL);
SC_P_SetSystemAnim(plid, 'X', 133, NULL);
SC_P_SetSystemAnim(plid, 'X', 134, NULL);
SC_P_SetSystemAnim(plid, 'X', 135, NULL);
SC_P_SetSystemAnim(plid, 'X', 136, NULL);
SC_P_SetSystemAnim(plid, 'X', 137, NULL);
SC_P_SetSystemAnim(plid, 'X', 140, NULL);
SC_P_SetSystemAnim(plid, 'X', 142, NULL);
}
//changes AI to use walk mode - only for peace
void P_SetWalk(sc_player plid){
s_SC_P_AI_MoveStyle movestyle;
dword list[8];
int count;
CLEAR(movestyle);
movestyle.peace.aim=0;
movestyle.peace.phase=0;
movestyle.peace.sprint=0;
movestyle.peace.flags=SC_P_AI_MOVESTYLE_FL_ALL;
SC_P_Ai_SetMoveStyle(plid, &movestyle);
SC_P_SetMoveSpeed(plid, 0, SC_P_MOVESPEED_STYLE_RUN, 1.5);
count=SC_P_GetWeapons(plid,list,8);
if (SC_P_GetSelectedWeapon(plid)!=56){
//has some weapons
//walking with gun
SC_P_SetSystemAnim(plid, 'X', 30, "g\\anims\\script anims\\walk007.stg");
SC_P_SetSystemAnim(plid, 'X', 34, "g\\anims\\script anims\\walk007.stg");
SC_P_SetSystemAnim(plid, 'X', 37, "g\\anims\\script anims\\walk007.stg");
SC_P_SetSystemAnim(plid, 'X', 70, "g\\anims\\script anims\\walk007.stg");
//walking without gun
SC_P_SetSystemAnim(plid, 'B', 30, "g\\anims\\script anims\\walk006.stg");
SC_P_SetSystemAnim(plid, 'B', 132, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'B', 133, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'B', 134, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'B', 140, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'B', 142, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'B', 135, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'B', 136, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'B', 137, "g\\anims\\script anims\\an140.stg");
} else {
SC_P_SetSystemAnim(plid, 'X', 30, "g\\anims\\script anims\\walk006.stg");
SC_P_SetSystemAnim(plid, 'X', 132, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'X', 133, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'X', 134, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'X', 140, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'X', 142, "g\\anims\\script anims\\an142.stg");
SC_P_SetSystemAnim(plid, 'X', 135, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'X', 136, "g\\anims\\script anims\\an140.stg");
SC_P_SetSystemAnim(plid, 'X', 137, "g\\anims\\script anims\\an140.stg");
}
}
//changes AI to use walk mode with gun - only for peace
void P_SetWalkGun(sc_player plid){
s_SC_P_AI_MoveStyle movestyle;
CLEAR(movestyle);
movestyle.peace.aim=0;
movestyle.peace.phase=0;
movestyle.peace.sprint=0;
movestyle.peace.flags=SC_P_AI_MOVESTYLE_FL_ALL;
SC_P_Ai_SetMoveStyle(plid, &movestyle);
SC_P_SetMoveSpeed(plid, 0, SC_P_MOVESPEED_STYLE_RUN, 1.5);
SC_P_SetSystemAnim(plid, 'A', 30, "g\\anims\\script anims\\walk007.stg");
}
//forces AI player to move in standing and aiming mode
void P_SetForcedAimMode(sc_player plid){
s_SC_P_AI_MoveStyle movestyle;
CLEAR(movestyle);
movestyle.peace.aim=1;
movestyle.peace.phase=0;
movestyle.peace.sprint=0;
movestyle.peace.flags=SC_P_AI_MOVESTYLE_FL_ALL;
movestyle.danger.aim=1;
movestyle.danger.phase=0;
movestyle.danger.sprint=0;
movestyle.danger.flags=SC_P_AI_MOVESTYLE_FL_ALL;
movestyle.battle.aim=1;
movestyle.battle.phase=0;
movestyle.battle.sprint=0;
movestyle.battle.flags=SC_P_AI_MOVESTYLE_FL_ALL;
SC_P_Ai_SetMoveStyle(plid, &movestyle);
}
//forces AI player to sprint
void P_SetForcedRunMode(sc_player plid){
s_SC_P_AI_MoveStyle movestyle;
CLEAR(movestyle);
movestyle.peace.aim=0;
movestyle.peace.phase=0;
movestyle.peace.sprint=1;
movestyle.peace.flags=SC_P_AI_MOVESTYLE_FL_ALL;
movestyle.danger.aim=0;
movestyle.danger.phase=0;
movestyle.danger.sprint=1;
movestyle.danger.flags=SC_P_AI_MOVESTYLE_FL_ALL;
movestyle.battle.aim=0;
movestyle.battle.phase=0;
movestyle.battle.sprint=1;
movestyle.battle.flags=SC_P_AI_MOVESTYLE_FL_ALL;
SC_P_Ai_SetMoveStyle(plid, &movestyle);
}
//returns nearest player from PC
sc_player P_GetNearestFromPC(float maxdist){
s_sphere sph;
float dist;
P_GetPos(SC_PC_Get(),&sph.pos);
sph.rad=maxdist;
return SC_GetNearestPlayer(&sph, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_AI_ONLY, &dist);
}
// returns nearest player from PC with specified side and group
sc_player P_GetNearestFromPC2(dword side, dword group, float maxdist){
s_sphere sph;
float dist,xdist;
s_SC_Area area;
sc_player list[32];
int plcount;
int i;
int chosen;
sc_player PC;
CLEAR(area);
PC=SC_PC_Get();
P_GetPos(PC,&sph.pos);
sph.rad=maxdist;
area.sphs=1;
area.sph=&sph;
plcount = SC_EnumPlayersArea(side, group, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_ALIVEONLY| SC_ENUMPLS_FL_AI_ONLY , &area);
if (!plcount) return 0;
dist = maxdist;
chosen=-1;
for (i=0; i<plcount; i++){
xdist=SC_P_GetDistancePl(PC,list[i]);
if (xdist<dist){
dist=xdist;
chosen=i;
}
}
if (chosen==-1) return 0;
return list[chosen];
}
BOOL P_InBattle(sc_player player){
s_SC_P_AI_status status;
SC_P_Ai_GetStatus(player,&status);
if (status.enemies) return TRUE;
return FALSE;
}
//returns true, if specified group is in battle contact with the enemy
BOOL GroupInBattle(dword side, dword group){
s_SC_P_AI_status status;
sc_player list[32];
int i, plcount;
CLEAR(list);
plcount=SC_EnumPlayers(side, group, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
for (i=0;i<plcount;i++){
CLEAR(status);
if (SC_P_Ai_GetStatus(list[i],&status)){
if (status.enemies) return TRUE;
}
}
return FALSE;
}
//will set radar on any nod specified by name
void SetRadar(char *nodname){
c_Vector3 pos;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,nodname),&pos);
SC_Radar_SetTarget(&pos);
}
//will clear the radar
void ClearRadar(){
SC_Radar_SetTarget(NULL);
}
//will send group to follow specified character (maybe used for hunt)
void G_FollowPlayer(int side, int group, sc_player player, BOOL enemy){
s_SC_P_Ai_MainTask mt;
sc_player list[64];
int num;
int i;
CLEAR(mt);
CLEAR(list);
mt.cooperation_id = 333;
mt.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_NOMOVE_WHEN_CHECKING_FAKEDANGER;
mt.target_pl = player;
mt.HO_search_dist = 5;
mt.HO_search_z_dist = 2;
mt.max_target_pl_dist = 15;
mt.max_target_pl_z_dist = 4;
mt.last_perc_in_group_moves = 0;
num=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return;
for (i=0;i<num;i++){
SC_P_Ai_StopMoving(list[i]);
SC_P_Ai_SetMainTask(list[i], &mt);
if (enemy) SC_P_Ai_Situation_UpdateEnemy(list[i],player);
}
}
BOOL P_InFight(sc_player player){
s_SC_P_AI_status aistat;
SC_P_Ai_GetStatus(player,&aistat);
if (aistat.enemies) return TRUE;
if (aistat.danger_around) return TRUE;
if (aistat.dangers_activated) return TRUE;
return FALSE;
}
//will return true if selected side group is in contact with the enemy (only real contact, not just dangers);
BOOL G_InFight(int side, int group){
sc_player list[32];
int num,i;
num=SC_EnumPlayers(side, group, list, 32, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return FALSE; //there is noone in the selected group, so no contact possible
for (i=0;i<num;i++){
if (P_InFight(list[i])) return TRUE;
}
return FALSE;
}
BOOL G_KnowsAboutPC(int side, int group){
sc_player list[32];
int num,i;
num=SC_EnumPlayers(side, group, list, 32, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY);
if (!num) return FALSE; //there is noone in the selected group, so no contact possible
for (i=0;i<num;i++){
if (SC_P_Ai_Situation_KnowsAbout(list[i],SC_PC_Get())) return TRUE;
}
return FALSE;
}
//will return number of the living characters in the group
int G_GetCount(int side, int group){
sc_player list[64];
CLEAR(list);
return SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY);
}
//returns random US weap
int GetUSWeapon(){
switch (rand()%5){
case 0:
case 1:
return 47;
case 2:
return 11;
case 3:
return 48;
case 4:
return 24;
}
return 47;
}
//returns random vc weap
int GetVCWeapon(){
switch (rand()%9){
case 0:
return 2;
case 1:
return 26;
case 2:
return 6;
case 3:
return 35;
case 4:
return 37;
case 5:
return 39;
default:
return 2;
}
return 2;
}
//sends player to specified nod
void P_WalkTo(sc_player player, char *name){
c_Vector3 target;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&target);
SC_P_Ai_MoveAt(player,&target,NULL,0);
}
void P_WalkTo(sc_player player, char *name, int callback){
c_Vector3 target;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&target);
SC_P_Ai_MoveAt(player,&target,NULL,callback);
}
//player will look at specified nod for a time (just watch)
void P_LookAt(sc_player player, char *name, float time){
s_SC_P_AI_WatchShoot watch;
CLEAR(watch);
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&watch.pos);
watch.time=time;
SC_P_Ai_SetWatchShoot(player, &watch);
}
void P_HunterKiller(sc_player player){
s_SC_P_Ai_MainTask maintask;
CLEAR(maintask);
maintask.cooperation_id=399;
maintask.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_MOVINGONPOSITION |
SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_TELLINGTOMOVE;// | SC_P_AI_MAINTASK_FL_NOMOVE_INBATTLE;
maintask.target_pl = SC_PC_Get();
maintask.min_enemy_dist=5;
maintask.HO_search_dist =5;
maintask.min_enemy_dist = 10;
maintask.max_enemy_dist = 20;
SC_P_Ai_SetMainTask(player, &maintask);
}
//sets specified group to hunt down SC_PC_Get()
void HunterKiller(int side, int group){
sc_player list[64];
int count,i;
s_SC_P_Ai_MainTask maintask;
CLEAR(list);
CLEAR(maintask);
count=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY);
if (!count) return;
maintask.cooperation_id=399;
maintask.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_MOVINGONPOSITION |
SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_TELLINGTOMOVE | SC_P_AI_MAINTASK_FL_NOMOVE_INBATTLE;
maintask.target_pl = SC_PC_Get();
maintask.HO_search_dist = 5;
maintask.min_enemy_dist = 10;
maintask.max_enemy_dist = 20;
for (i=0;i<count;i++){
SC_P_Ai_SetMainTask(list[i], &maintask);
}
}
//suicide attackers
void CrazyHunterKiller(int side, int group){
sc_player list[64];
int count,i;
s_SC_P_Ai_MainTask maintask;
CLEAR(list);
CLEAR(maintask);
count=SC_EnumPlayers(side, group, list, 64, SC_ENUMPLS_FL_ALIVEONLY | SC_ENUMPLS_FL_RESPAWNEDONLY);
if (!count) return;
maintask.cooperation_id=399;
maintask.flags = SC_P_AI_MAINTASK_FL_PERMANENT | SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_MOVINGONPOSITION |
SC_P_AI_MAINTASK_FL_DISABLE_GENSPEECH_TELLINGTOMOVE | SC_P_AI_MAINTASK_FL_ALLOW_MOVE_TO_NOCOVER;
maintask.target_pl = SC_PC_Get();
maintask.HO_search_dist = 5;
maintask.min_enemy_dist = 5;
maintask.max_enemy_dist = 10;
for (i=0;i<count;i++){
SC_P_Ai_SetMainTask(list[i], &maintask);
}
}
//sets player on position, best to use hideout name
void P_SetPos(sc_player player, char *name){
c_Vector3 vec;
float rot;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&vec);
rot=SC_NOD_GetWorldRotZ(SC_NOD_Get(NULL,name));
SC_P_SetPos(player,&vec,NULL,&rot);
}
void PC_SetPos(char *name){
c_Vector3 vec;
float rot;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&vec);
rot=SC_NOD_GetWorldRotZ(SC_NOD_Get(NULL,name));
SC_P_SetPos(SC_PC_Get(),&vec,NULL,&rot);
}
//enable interaction
void EnableInteraction(sc_player player, int inttext){
s_SC_P_Interaction interinfo;
CLEAR(interinfo);
interinfo.active_distance=2;
interinfo.items=1;
interinfo.item[0].txt_nr=inttext;
SC_P_SetInteraction(player,&interinfo);
}
#define DisableInteraction(player) SC_P_SetInteraction(player,NULL)
//kills everyone in the helper
void KillHelper(char *helper){
int i, count;
s_SC_Area area;
sc_player list[32];
c_BoxOriented box;
s_sphere sph;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
count =SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_ALIVEONLY, &area);
for (i=0;i<count;i++)
SC_P_MakeDamage(list[i],500);
}
//derespawns all ai in the helper
void DerespHelper(char *helper){
int i, count;
s_SC_Area area;
sc_player list[32];
c_BoxOriented box;
s_sphere sph;
CLEAR(area);
switch (SC_GetScriptHelper(helper,&sph,&box)){
case SC_SCRIPTHELPER_TYPE_ERROR:
return;
case SC_SCRIPTHELPER_TYPE_SPHERE:
area.sphs=1;
area.sph=&sph;
break;
case SC_SCRIPTHELPER_TYPE_BOX:
area.boxes=1;
area.box=&box;
break;
}
count =SC_EnumPlayersArea(SC_P_SIDE_ALL, SC_P_GROUP_ALL, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY, &area);
for (i=0;i<count;i++)
SC_P_Derespawn(list[i]);
}
//all ai in the group will be sent info about PC (for enemies only!)
void GroupUpdatePC(int side, int group){
int i, count;
sc_player list[32];
count =SC_EnumPlayers(side, group, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY | SC_ENUMPLS_FL_ALIVEONLY);
for (i=0;i<count;i++)
SC_P_Ai_Situation_UpdateEnemy(list[i],SC_PC_Get());
}
void KillGroup(int side, int group){
int i, count;
sc_player list[32];
count =SC_EnumPlayers(side, group, list, 32, SC_ENUMPLS_FL_RESPAWNEDONLY | SC_ENUMPLS_FL_AI_ONLY | SC_ENUMPLS_FL_ALIVEONLY);
for (i=0;i<count;i++)
SC_P_MakeDamage(list[i],800);
}
void G_SendMessage(int side, int group, dword param1, dword param2){
//will send message to ALL (including dead) players in the group
sc_player list[64];
int count,i;
count = SC_EnumPlayers(side, group, list, 32, 0);
for (i=0; i<count; i++){
SC_P_ScriptMessage(list[i],param1,param2);
}
}
void P_Watch(sc_player plid, char *name, float time){
s_SC_P_AI_WatchShoot watch;
if (!name){
SC_P_Ai_SetWatchShoot(plid, NULL);
return;
}
CLEAR(watch);
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&watch.pos);
if (!time) watch.time=99999;
else watch.time=time;
SC_P_Ai_SetWatchShoot(plid, &watch);
}
void P_WatchP(sc_player plid, sc_player target, float time){
s_SC_P_AI_WatchShoot watch;
if (!target){
SC_P_Ai_SetWatchShoot(plid, NULL);
return;
}
CLEAR(watch);
watch.player=target;
if (!time) watch.time=99999;
else watch.time=time;
SC_P_Ai_SetWatchShoot(plid, &watch);
}
//aimed shot
void P_ShootP(sc_player plid, sc_player target,float time){
s_SC_P_AI_WatchShoot watch;
if (!target){
return;
}
CLEAR(watch);
watch.player=target;
if (!time) watch.time=99999;
else watch.time=time;
watch.flags=SC_P_AI_WATCHSHOOT_FL_SHOOT|SC_P_AI_WATCHSHOOT_FL_PHASE_CURRENT;
watch.aim=1;
SC_P_Ai_SetWatchShoot(plid, &watch);
}
void P_SetDamage(sc_player player, float received){
s_SC_P_ScriptProps sc_props;
CLEAR(sc_props);
SC_P_GetScriptProps(player, &sc_props);
sc_props.received_damage_mult = received;
SC_P_SetScriptProps(player, &sc_props);
}
BOOL P_CheckId(sc_player player, dword side, dword group, dword member){
dword sid,gr,mem;
if (!player) return FALSE;
SC_P_GetSideGroupMemberId(player,&sid,&gr,&mem);
if (mem!=member) return FALSE;
if (gr!=group) return FALSE;
if (mem!=member) return FALSE;
return TRUE;
}
void P_GiveGun(sc_player player, int gun){
int gcount=0;
int glist[20];
gcount=SC_P_GetWeapons(player,glist,20);
glist[gcount]=gun;
gcount++;
SC_P_SetWeapons(player,glist,gcount,gun);
}
#define NOD_GetPos(name, pos) SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),pos)
float P_Distance(sc_player player, char *name){
c_Vector3 vec;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,name),&vec);
return SC_P_GetDistancePos(player,&vec);
}
float P_GetVisibility(sc_player player){
s_SC_P_AI_props aip;
SC_P_Ai_GetProps(player,&aip);
return aip.max_visibility;
}
void P_SetVisibility(sc_player player, float maxd){
s_SC_P_AI_props aip;
SC_P_Ai_GetProps(player,&aip);
aip.max_visibility=maxd;
SC_P_Ai_SetProps(player,&aip);
}
//returns true if PC has full health
BOOL PC_Healthy(){
s_SC_P_status pstat;
if (!SC_P_GetStatus(SC_PC_Get(),&pstat)) return FALSE;
if (pstat.hp==pstat.max_hp) return TRUE;
return FALSE;
}
// returns true if PC has at least half of hp
BOOL PC_HalfHealth(){
s_SC_P_status pstat;
if (!SC_P_GetStatus(SC_PC_Get(),&pstat)) return FALSE;
if (pstat.hp>(pstat.max_hp/2)) return TRUE;
return FALSE;
}
/*
float abs(float x){
if (x>0) return x;
else return -x;
}
*/
float P_GetDistNod(sc_player player, char *nodname){
c_Vector3 pos;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,nodname),&pos);
return SC_P_GetDistancePos(player,&pos);
}
float GetDistVec(c_Vector3 *vec, char *nodname){
c_Vector3 pos;
SC_NOD_GetWorldPos(SC_NOD_Get(NULL,nodname),&pos);
return SC_2VectorsDist(vec,&pos);
}
dword GetWeaponItemType(dword gun){
s_SC_TweapInfo tweap;
SC_TWEAP_GetInfo(gun,&tweap);
return tweap.item_type;
}
//returns item type of ammo for the the selected weapon
dword GetAmmoItemType(dword gun){
s_SC_TweapInfo tweap;
SC_TWEAP_GetInfo(gun,&tweap);
return tweap.ammo_itemtype[0];
}
BOOL P_IsMoving(sc_player player){
s_sphere prev[5],cur[5];
if (SC_P_GetMovingState(player, prev, cur)) return TRUE;
return FALSE;
}
void PC_DisableBino(){
s_SC_PC_Control control;
SC_PC_GetControl(&control);
control.use_binocular=FALSE;
SC_PC_SetControl(&control);
}
#endif
VC_Officer_01 (which the group_01 AI will follow into battle)...this can be modified for a second officer by changing group and member ID (i think)...has to be tested by YOU...(dont forget to also alter the script for the second soldier group as well...
//generic VC soldier
//accepts redefinitions:
//GROUP, MEMBERID, NAME_NR
//CLASS, RANK, AIFLAG
//SECONDARYCLASS - with RANDOMCLASS percent chance will set the secondary class
//can use RESPAWNGPHASE to specify levelphase when soldier will be respawned
//can use GENERICVOICE to redefine generic voice group for player
//can use VEHICLELINK (position) and VEHICLENAME to link after start to vehicle
//can use MEDIK or ENGINEER to make soldier medic or engineer
//can use IMMORTAL to make player immortal
//can use #define TOUGHGUY to make player much more stronger
//use #define REDEFINEMAIN for user main, main function from this file will be renamed to SoldierMain()
#define REDEFINEMAIN
#include <inc\sc_global.h>
#include <inc\sc_def.h>
#include <..\..\levels\wasteland\data\wasteland_mp\scripts\library.cxx>
#include <inc\all\ai.cxx>
#ifndef GROUP
#define GROUP 0
#endif
#ifndef MEMBERID
#define MEMBERID 1
#endif
#ifndef NAME_NR
#define NAME_NR 2742
#endif
#ifndef RANK
#define RANK RNK_6
#endif
#ifndef CLASS
#define CLASS CLS_SOLDIER
#endif
#ifndef AIFLAG
#define AIFLAG 0
#endif
dword gPhase = 0;
int aiclass=0;
dword myweapon;
void CreatePlayer(s_SC_Pscript_info *info){
s_SC_P_Create create_info;
s_SC_P_RespawnPos resp_pos;
s_SC_Plscr_info plscr_info;
s_PlayerIniEqp ini_eqp;
s_SC_P_CreateWeap weap[3];
s_SC_P_AmmoRedefine amred[1];
CLEAR(plscr_info);
SC_PlScr_GetInfo(info->script, &plscr_info);
CLEAR(resp_pos);
SC_NOD_FillRespawnPos(plscr_info.nod, &resp_pos);
CLEAR(create_info);
create_info.script = info->script;
create_info.type = SC_P_CREATE_TYPE_AI;
create_info.flags = SC_P_CREATE_FL_GENERATE_AI_BLOCKER;
#ifdef ALLOWCOMA
create_info.flags |= SC_P_CREATE_FL_ALLOW_COMA;
#endif
#ifdef ONLYCOMA
create_info.flags |= SC_P_CREATE_FL_NODEADJUSTCOMA;
#endif
#ifdef ALWAYSDEATHINIK
create_info.flags |= SC_P_CREATE_FL_FORCE_USE_IK_DEATH;
#endif
create_info.side = SC_P_SIDE_VC;
create_info.group = GROUP;
create_info.member_id = MEMBERID;
create_info.name_nr = NAME_NR;
#ifdef CLASSNAME
create_info.class_name_id = CLASSNAME;
#endif
#ifdef RESPAWNGPHASE
create_info.respawn = NULL;
#else
create_info.respawn = &resp_pos;
#endif
#ifdef GENERICVOICE
create_info.genvoice_group=GENERICVOICE;
#endif
aiclass=CLASS;
#ifdef SECONDARYCLASS
if ((rand()%100)<=RANDOMCLASS) aiclass=SECONDARYCLASS;
#endif
vcGetPlayerIniEqp(RANK,aiclass,SUB_RND,&ini_eqp);
#ifdef FORCEMAINGUN
weap[0].weap_id=FORCEMAINGUN;
#else
weap[0].weap_id=ini_eqp.weapon;
#endif
myweapon=weap[0].weap_id;
create_info.weapons = 1;
#ifdef MEDIK
weap[1].weap_id=60;
create_info.weapons = 2;
amred[0].ammo_type = 22; //medkit 'ammo'
amred[0].max_ammo = 1000; //ammo amount
create_info.ammo_redefines = 1;
create_info.ammo_redefine = amred;
#else
if (!(rand() % (SC_GetDifficulty()+3))){
weap[create_info.weapons].weap_id=60;
create_info.weapons++;
}
#endif
#ifdef ENGINEER
weap[1].weap_id=61;
create_info.weapons = 2;
amred[0].ammo_type = 23; //'ammo'
amred[0].max_ammo = 1000; //ammo amount
create_info.ammo_redefines = 1;
create_info.ammo_redefine = amred;
#endif
#ifdef ADDGRENADE
weap[create_info.weapons].weap_id=70;
create_info.weapons++;
#endif
create_info.weap = weap;
create_info.inifile=ini_eqp.bodyIni;
create_info.eqp_inifile=ini_eqp.bodyEqp;
create_info.head_name=ini_eqp.headIni;
create_info.head_eqp_inifile=ini_eqp.headEqp;
#ifdef REDEFINIFILENAME
create_info.inifile=REDEFINIFILENAME;
#endif
#ifdef BODYEQP
create_info.eqp_inifile=BODYEQP;
#endif
#ifdef HEAD
create_info.head_name=HEAD;
#endif
#ifdef HEADEQP
create_info.head_eqp_inifile=HEADEQP;
#endif
SC_P_Create(&create_info);
}
#ifdef REDEFINEMAIN
int SoldierMain(s_SC_Pscript_info *info){
#else
int ScriptMain(s_SC_Pscript_info *info){
#endif
s_SC_P_status status;
s_SC_P_RespawnPos resp_pos;
s_SC_Plscr_info plscr_info;
s_SC_P_ScriptProps sc_props;
s_SC_P_Ai_Medik mp;
switch(info->message){
case SC_PLSCR_MSG_SCRIPT_INIT:
CreatePlayer(info);
break;
case SC_PLSCR_MSG_SCRIPT_RELEASE:
break;
case SC_PLSCR_MSG_PL_CREATED:
break;
case SC_PLSCR_MSG_PL_RELEASED:
break;
case SC_PLSCR_MSG_PL_RESPAWNED:
gPhase = 2;
break;
case SC_PLSCR_MSG_PL_DERESPAWNED:
gPhase = 666;
break;
case SC_PLSCR_MSG_SCRIPT_TIMETICK:
switch(gPhase) {
case 0:
#ifdef RESPAWNGPHASE
if (GetLevelPhase >= RESPAWNGPHASE ){
CLEAR(plscr_info);
SC_PlScr_GetInfo(info->script, &plscr_info);
CLEAR(resp_pos);
SC_NOD_FillRespawnPos(plscr_info.nod, &resp_pos);
SC_P_Respawn(info->player, &resp_pos);
gPhase=1;
}
#endif
break;
case 2:
CLEAR(status);
if (!SC_P_GetStatus(info->player, &status)) return 0;
#ifdef FAKERANK
SetRankClass(info->player,SC_GetDifficulty(),FAKERANK,aiclass,AIFLAG);
#else
SetRankClass(info->player,SC_GetDifficulty(),RANK,aiclass,AIFLAG);
#endif
#ifdef VEHICLELINK
SC_P_Vehicle_Link(info->player, SC_NOD_Get(NULL,VEHICLENAME),VEHICLELINK);
#endif
#ifdef IMMORTAL
CLEAR(sc_props);
SC_P_GetScriptProps(info->player, &sc_props);
sc_props.received_damage_mult = 0.0f;
SC_P_SetScriptProps(info->player, &sc_props);
#else
#ifdef TOUGHGUY
CLEAR(sc_props);
SC_P_GetScriptProps(info->player, &sc_props);
sc_props.received_damage_mult = 0.1f;
SC_P_SetScriptProps(info->player, &sc_props);
#endif
#endif
#ifdef MEDIK
SC_P_Ai_Medik_GetProps(info->player, &mp);
mp.peace.range = 30;
mp.peace.hp_percentage = 0.8f;
mp.battle.range = 12;
mp.battle.hp_percentage = 0.5f;
SC_P_Ai_Medik_SetProps(info->player, &mp);
#endif
#ifdef SCRIPTMODEON
SC_P_Ai_SetScriptMode(info->player,TRUE);
#endif
#ifdef STANDSTATIV
SC_P_SetAnimsVariations(info->player, SC_P_ANIMVARIATION_DISABLE_ALL);
SC_P_SetSystemAnim(info->player, 'X', 0, STANDSTATIV);
#endif
#ifdef FACETYPE
SC_P_Grimace_Set(info->player,FACETYPE,0,0);
#endif
gPhase = 10;
break;
case 10:
break;
case 666:
//I am derespawned
break;
}
break;
case SC_PLSCR_MSG_PL_HIT:
break;
case SC_PLSCR_MSG_PL_KILLED:
gPhase=777;
break;
}// switch(info->message)
return 1;
}// int ScriptMain(s_SC_P_info *info)
int ScriptMain(s_SC_Pscript_info *info){
switch(info->message){
case SC_PLSCR_MSG_SCRIPT_TIMETICK:
switch(gPhase) {
case 10:
info->next_exe_time=5;
G_MoveToHelper(1,0,"target_01", 1);
gPhase=20;
break;
}
break;
}// switch(info->message)
return SoldierMain(info);
}// int ScriptMain(s_SC_P_info *info)
And finally the VC squad...The VC squad must match the group number of the officer...They will follow this officer into battle and they will all fight while grouped together until they all die while fighting grouped together...
//generic VC soldier
//accepts redefinitions:
//GROUP, MEMBERID, NAME_NR
//CLASS, RANK, AIFLAG
//SECONDARYCLASS - with RANDOMCLASS percent chance will set the secondary class
//can use RESPAWNGPHASE to specify levelphase when soldier will be respawned
//can use GENERICVOICE to redefine generic voice group for player
//can use VEHICLELINK (position) and VEHICLENAME to link after start to vehicle
//can use MEDIK or ENGINEER to make soldier medic or engineer
//can use IMMORTAL to make player immortal
//can use #define TOUGHGUY to make player much more stronger
//use #define REDEFINEMAIN for user main, main function from this file will be renamed to SoldierMain()
#include <inc\sc_global.h>
#include <inc\sc_def.h>
#include <inc\shigor\library.cxx>
#include <inc\all\ai.cxx>
#ifndef GROUP
#define GROUP 0
#endif
#ifndef MEMBERID
#define MEMBERID SC_P_CREATE_MEMID_AUTO
#endif
#ifndef NAME_NR
#define NAME_NR 2739
#endif
#ifndef RANK
#define RANK RNK_1
#endif
#ifndef CLASS
#define CLASS CLS_SOLDIER
#endif
#ifndef AIFLAG
#define AIFLAG 0
#endif
dword gPhase = 0;
int aiclass=0;
dword myweapon;
void CreatePlayer(s_SC_Pscript_info *info){
s_SC_P_Create create_info;
s_SC_P_RespawnPos resp_pos;
s_SC_Plscr_info plscr_info;
s_PlayerIniEqp ini_eqp;
s_SC_P_CreateWeap weap[3];
s_SC_P_AmmoRedefine amred[1];
CLEAR(plscr_info);
SC_PlScr_GetInfo(info->script, &plscr_info);
CLEAR(resp_pos);
SC_NOD_FillRespawnPos(plscr_info.nod, &resp_pos);
CLEAR(create_info);
create_info.script = info->script;
create_info.type = SC_P_CREATE_TYPE_AI;
create_info.flags = SC_P_CREATE_FL_GENERATE_AI_BLOCKER;
#ifdef ALLOWCOMA
create_info.flags |= SC_P_CREATE_FL_ALLOW_COMA;
#endif
#ifdef ONLYCOMA
create_info.flags |= SC_P_CREATE_FL_NODEADJUSTCOMA;
#endif
#ifdef ALWAYSDEATHINIK
create_info.flags |= SC_P_CREATE_FL_FORCE_USE_IK_DEATH;
#endif
create_info.side = SC_P_SIDE_VC;
create_info.group = GROUP;
create_info.member_id = MEMBERID;
create_info.name_nr = NAME_NR;
#ifdef CLASSNAME
create_info.class_name_id = CLASSNAME;
#endif
#ifdef RESPAWNGPHASE
create_info.respawn = NULL;
#else
create_info.respawn = &resp_pos;
#endif
#ifdef GENERICVOICE
create_info.genvoice_group=GENERICVOICE;
#endif
aiclass=CLASS;
#ifdef SECONDARYCLASS
if ((rand()%100)<=RANDOMCLASS) aiclass=SECONDARYCLASS;
#endif
vcGetPlayerIniEqp(RANK,aiclass,SUB_RND,&ini_eqp);
#ifdef FORCEMAINGUN
weap[0].weap_id=FORCEMAINGUN;
#else
weap[0].weap_id=ini_eqp.weapon;
#endif
myweapon=weap[0].weap_id;
create_info.weapons = 1;
#ifdef MEDIK
weap[1].weap_id=60;
create_info.weapons = 2;
amred[0].ammo_type = 22; //medkit 'ammo'
amred[0].max_ammo = 1000; //ammo amount
create_info.ammo_redefines = 1;
create_info.ammo_redefine = amred;
#else
if (!(rand() % (SC_GetDifficulty()+3))){
weap[create_info.weapons].weap_id=60;
create_info.weapons++;
}
#endif
#ifdef ENGINEER
weap[1].weap_id=61;
create_info.weapons = 2;
amred[0].ammo_type = 23; //'ammo'
amred[0].max_ammo = 1000; //ammo amount
create_info.ammo_redefines = 1;
create_info.ammo_redefine = amred;
#endif
#ifdef ADDGRENADE
weap[create_info.weapons].weap_id=70;
create_info.weapons++;
#endif
create_info.weap = weap;
create_info.inifile=ini_eqp.bodyIni;
create_info.eqp_inifile=ini_eqp.bodyEqp;
create_info.head_name=ini_eqp.headIni;
create_info.head_eqp_inifile=ini_eqp.headEqp;
#ifdef REDEFINIFILENAME
create_info.inifile=REDEFINIFILENAME;
#endif
#ifdef BODYEQP
create_info.eqp_inifile=BODYEQP;
#endif
#ifdef HEAD
create_info.head_name=HEAD;
#endif
#ifdef HEADEQP
create_info.head_eqp_inifile=HEADEQP;
#endif
SC_P_Create(&create_info);
}
#ifdef REDEFINEMAIN
int SoldierMain(s_SC_Pscript_info *info){
#else
int ScriptMain(s_SC_Pscript_info *info){
#endif
s_SC_P_status status;
s_SC_P_RespawnPos resp_pos;
s_SC_Plscr_info plscr_info;
s_SC_P_ScriptProps sc_props;
s_SC_P_Ai_Medik mp;
switch(info->message){
case SC_PLSCR_MSG_SCRIPT_INIT:
CreatePlayer(info);
break;
case SC_PLSCR_MSG_SCRIPT_RELEASE:
break;
case SC_PLSCR_MSG_PL_CREATED:
break;
case SC_PLSCR_MSG_PL_RELEASED:
break;
case SC_PLSCR_MSG_PL_RESPAWNED:
gPhase = 2;
break;
case SC_PLSCR_MSG_PL_DERESPAWNED:
gPhase = 666;
break;
case SC_PLSCR_MSG_SCRIPT_TIMETICK:
switch(gPhase) {
case 0:
#ifdef RESPAWNGPHASE
if (GetLevelPhase >= RESPAWNGPHASE ){
CLEAR(plscr_info);
SC_PlScr_GetInfo(info->script, &plscr_info);
CLEAR(resp_pos);
SC_NOD_FillRespawnPos(plscr_info.nod, &resp_pos);
SC_P_Respawn(info->player, &resp_pos);
gPhase=1;
}
#endif
break;
case 2:
CLEAR(status);
if (!SC_P_GetStatus(info->player, &status)) return 0;
#ifdef FAKERANK
SetRankClass(info->player,SC_GetDifficulty(),FAKERANK,aiclass,AIFLAG);
#else
SetRankClass(info->player,SC_GetDifficulty(),RANK,aiclass,AIFLAG);
#endif
#ifdef VEHICLELINK
SC_P_Vehicle_Link(info->player, SC_NOD_Get(NULL,VEHICLENAME),VEHICLELINK);
#endif
#ifdef IMMORTAL
CLEAR(sc_props);
SC_P_GetScriptProps(info->player, &sc_props);
sc_props.received_damage_mult = 0.0f;
SC_P_SetScriptProps(info->player, &sc_props);
#else
#ifdef TOUGHGUY
CLEAR(sc_props);
SC_P_GetScriptProps(info->player, &sc_props);
sc_props.received_damage_mult = 0.1f;
SC_P_SetScriptProps(info->player, &sc_props);
#endif
#endif
#ifdef MEDIK
SC_P_Ai_Medik_GetProps(info->player, &mp);
mp.peace.range = 30;
mp.peace.hp_percentage = 0.8f;
mp.battle.range = 12;
mp.battle.hp_percentage = 0.5f;
SC_P_Ai_Medik_SetProps(info->player, &mp);
#endif
#ifdef SCRIPTMODEON
SC_P_Ai_SetScriptMode(info->player,TRUE);
#endif
#ifdef STANDSTATIV
SC_P_SetAnimsVariations(info->player, SC_P_ANIMVARIATION_DISABLE_ALL);
SC_P_SetSystemAnim(info->player, 'X', 0, STANDSTATIV);
#endif
#ifdef FACETYPE
SC_P_Grimace_Set(info->player,FACETYPE,0,0);
#endif
gPhase = 10;
break;
case 10:
break;
case 666:
//I am derespawned
break;
}
break;
case SC_PLSCR_MSG_PL_HIT:
break;
case SC_PLSCR_MSG_PL_KILLED:
gPhase=777;
break;
}// switch(info->message)
return 1;
}// int ScriptMain(s_SC_P_info *info)
**Important**, i believe you have to utilize script helpers with this script...If you look into the library.cxx file there are helpers listed as (s_sphere or sph, c_BoxOriented or box, s_SC_Area or area)...the group AI will go to these spheres, boxes, and areas just like they utilize waypoints...I forgot how to make the box, but i believe this is their ultimate goal is to guard the box...and they utilize the spheres to get there...the area is aound those two helpers...damn it has been a while!
Don't forget what i said above about me not having the VC2 game installed, and also the VC2 editor and tools installed...this has to be messed with by YOU or someone else which may know how to implement it...
Good Luck!
Rick (Chavez_US)