codemp/game/ai_util.c

Go to the documentation of this file.
00001 #include "g_local.h"
00002 #include "q_shared.h"
00003 #include "botlib.h"
00004 #include "ai_main.h"
00005 
00006 #ifdef BOT_ZMALLOC
00007 #define MAX_BALLOC 8192
00008 
00009 void *BAllocList[MAX_BALLOC];
00010 #endif
00011 
00012 char gBotChatBuffer[MAX_CLIENTS][MAX_CHAT_BUFFER_SIZE];
00013 
00014 void *B_TempAlloc(int size)
00015 {
00016         return BG_TempAlloc(size);
00017 }
00018 
00019 void B_TempFree(int size)
00020 {
00021         BG_TempFree(size);
00022 }
00023 
00024 
00025 void *B_Alloc(int size)
00026 {
00027 #ifdef BOT_ZMALLOC
00028         void *ptr = NULL;
00029         int i = 0;
00030 
00031 #ifdef BOTMEMTRACK
00032         int free = 0;
00033         int used = 0;
00034 
00035         while (i < MAX_BALLOC)
00036         {
00037                 if (!BAllocList[i])
00038                 {
00039                         free++;
00040                 }
00041                 else
00042                 {
00043                         used++;
00044                 }
00045 
00046                 i++;
00047         }
00048 
00049         G_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
00050 
00051         i = 0;
00052 #endif
00053 
00054         ptr = trap_BotGetMemoryGame(size);
00055 
00056         while (i < MAX_BALLOC)
00057         {
00058                 if (!BAllocList[i])
00059                 {
00060                         BAllocList[i] = ptr;
00061                         break;
00062                 }
00063                 i++;
00064         }
00065 
00066         if (i == MAX_BALLOC)
00067         {
00068                 //If this happens we'll have to rely on this chunk being freed manually with B_Free, which it hopefully will be
00069 #ifdef DEBUG
00070                 G_Printf("WARNING: MAXIMUM B_ALLOC ALLOCATIONS EXCEEDED\n");
00071 #endif
00072         }
00073 
00074         return ptr;
00075 #else
00076 
00077         return BG_Alloc(size);
00078 
00079 #endif
00080 }
00081 
00082 void B_Free(void *ptr)
00083 {
00084 #ifdef BOT_ZMALLOC
00085         int i = 0;
00086 
00087 #ifdef BOTMEMTRACK
00088         int free = 0;
00089         int used = 0;
00090 
00091         while (i < MAX_BALLOC)
00092         {
00093                 if (!BAllocList[i])
00094                 {
00095                         free++;
00096                 }
00097                 else
00098                 {
00099                         used++;
00100                 }
00101 
00102                 i++;
00103         }
00104 
00105         G_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
00106 
00107         i = 0;
00108 #endif
00109 
00110         while (i < MAX_BALLOC)
00111         {
00112                 if (BAllocList[i] == ptr)
00113                 {
00114                         BAllocList[i] = NULL;
00115                         break;
00116                 }
00117 
00118                 i++;
00119         }
00120 
00121         if (i == MAX_BALLOC)
00122         {
00123                 //Likely because the limit was exceeded and we're now freeing the chunk manually as we hoped would happen
00124 #ifdef DEBUG
00125                 G_Printf("WARNING: Freeing allocation which is not in the allocation structure\n");
00126 #endif
00127         }
00128 
00129         trap_BotFreeMemoryGame(ptr);
00130 #endif
00131 }
00132 
00133 void B_InitAlloc(void)
00134 {
00135 #ifdef BOT_ZMALLOC
00136         memset(BAllocList, 0, sizeof(BAllocList));
00137 #endif
00138 
00139         memset(gWPArray, 0, sizeof(gWPArray));
00140 }
00141 
00142 void B_CleanupAlloc(void)
00143 {
00144 #ifdef BOT_ZMALLOC
00145         int i = 0;
00146 
00147         while (i < MAX_BALLOC)
00148         {
00149                 if (BAllocList[i])
00150                 {
00151                         trap_BotFreeMemoryGame(BAllocList[i]);
00152                         BAllocList[i] = NULL;
00153                 }
00154 
00155                 i++;
00156         }
00157 #endif
00158 }
00159 
00160 int GetValueGroup(char *buf, char *group, char *outbuf)
00161 {
00162         char *place, *placesecond;
00163         int iplace;
00164         int failure;
00165         int i;
00166         int startpoint, startletter;
00167         int subg = 0;
00168 
00169         i = 0;
00170 
00171         iplace = 0;
00172 
00173         place = strstr(buf, group);
00174 
00175         if (!place)
00176         {
00177                 return 0;
00178         }
00179 
00180         startpoint = place - buf + strlen(group) + 1;
00181         startletter = (place - buf) - 1;
00182 
00183         failure = 0;
00184 
00185         while (buf[startpoint+1] != '{' || buf[startletter] != '\n')
00186         {
00187                 placesecond = strstr(place+1, group);
00188 
00189                 if (placesecond)
00190                 {
00191                         startpoint += (placesecond - place);
00192                         startletter += (placesecond - place);
00193                         place = placesecond;
00194                 }
00195                 else
00196                 {
00197                         failure = 1;
00198                         break;
00199                 }
00200         }
00201 
00202         if (failure)
00203         {
00204                 return 0;
00205         }
00206 
00207         //we have found the proper group name if we made it here, so find the opening brace and read into the outbuf
00208         //until hitting the end brace
00209 
00210         while (buf[startpoint] != '{')
00211         {
00212                 startpoint++;
00213         }
00214 
00215         startpoint++;
00216 
00217         while (buf[startpoint] != '}' || subg)
00218         {
00219                 if (buf[startpoint] == '{')
00220                 {
00221                         subg++;
00222                 }
00223                 else if (buf[startpoint] == '}')
00224                 {
00225                         subg--;
00226                 }
00227                 outbuf[i] = buf[startpoint];
00228                 i++;
00229                 startpoint++;
00230         }
00231         outbuf[i] = '\0';
00232 
00233         return 1;
00234 }
00235 
00236 int GetPairedValue(char *buf, char *key, char *outbuf)
00237 {
00238         char *place, *placesecond;
00239         int startpoint, startletter;
00240         int i, found;
00241 
00242         if (!buf || !key || !outbuf)
00243         {
00244                 return 0;
00245         }
00246 
00247         i = 0;
00248 
00249         while (buf[i] && buf[i] != '\0')
00250         {
00251                 if (buf[i] == '/')
00252                 {
00253                         if (buf[i+1] && buf[i+1] != '\0' && buf[i+1] == '/')
00254                         {
00255                                 while (buf[i] != '\n')
00256                                 {
00257                                         buf[i] = '/';
00258                                         i++;
00259                                 }
00260                         }
00261                 }
00262                 i++;
00263         }
00264 
00265         place = strstr(buf, key);
00266 
00267         if (!place)
00268         {
00269                 return 0;
00270         }
00271         //tab == 9
00272         startpoint = place - buf + strlen(key);
00273         startletter = (place - buf) - 1;
00274 
00275         found = 0;
00276 
00277         while (!found)
00278         {
00279                 if (startletter == 0 || !buf[startletter] || buf[startletter] == '\0' || buf[startletter] == 9 || buf[startletter] == ' ' || buf[startletter] == '\n')
00280                 {
00281                         if (buf[startpoint] == '\0' || buf[startpoint] == 9 || buf[startpoint] == ' ' || buf[startpoint] == '\n')
00282                         {
00283                                 found = 1;
00284                                 break;
00285                         }
00286                 }
00287 
00288                 placesecond = strstr(place+1, key);
00289 
00290                 if (placesecond)
00291                 {
00292                         startpoint += placesecond - place;
00293                         startletter += placesecond - place;
00294                         place = placesecond;
00295                 }
00296                 else
00297                 {
00298                         place = NULL;
00299                         break;
00300                 }
00301 
00302         }
00303 
00304         if (!found || !place || !buf[startpoint] || buf[startpoint] == '\0')
00305         {
00306                 return 0;
00307         }
00308 
00309         while (buf[startpoint] == ' ' || buf[startpoint] == 9 || buf[startpoint] == '\n')
00310         {
00311                 startpoint++;
00312         }
00313 
00314         i = 0;
00315 
00316         while (buf[startpoint] && buf[startpoint] != '\0' && buf[startpoint] != '\n')
00317         {
00318                 outbuf[i] = buf[startpoint];
00319                 i++;
00320                 startpoint++;
00321         }
00322 
00323         outbuf[i] = '\0';
00324 
00325         return 1;
00326 }
00327 
00328 int BotDoChat(bot_state_t *bs, char *section, int always)
00329 {
00330         char *chatgroup;
00331         int rVal;
00332         int inc_1;
00333         int inc_2;
00334         int inc_n;
00335         int lines;
00336         int checkedline;
00337         int getthisline;
00338         gentity_t *cobject;
00339 
00340         if (!bs->canChat)
00341         {
00342                 return 0;
00343         }
00344 
00345         if (bs->doChat)
00346         { //already have a chat scheduled
00347                 return 0;
00348         }
00349 
00350         if (trap_Cvar_VariableIntegerValue("se_language"))
00351         { //no chatting unless English.
00352                 return 0;
00353         }
00354 
00355         if (Q_irand(1, 10) > bs->chatFrequency && !always)
00356         {
00357                 return 0;
00358         }
00359 
00360         bs->chatTeam = 0;
00361 
00362         chatgroup = (char *)B_TempAlloc(MAX_CHAT_BUFFER_SIZE);
00363 
00364         rVal = GetValueGroup(gBotChatBuffer[bs->client], section, chatgroup);
00365 
00366         if (!rVal) //the bot has no group defined for the specified chat event
00367         {
00368                 B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
00369                 return 0;
00370         }
00371 
00372         inc_1 = 0;
00373         inc_2 = 2;
00374 
00375         while (chatgroup[inc_2] && chatgroup[inc_2] != '\0')
00376         {
00377                 if (chatgroup[inc_2] != 13 && chatgroup[inc_2] != 9)
00378                 {
00379                         chatgroup[inc_1] = chatgroup[inc_2];
00380                         inc_1++;
00381                 }
00382                 inc_2++;
00383         }
00384         chatgroup[inc_1] = '\0';
00385 
00386         inc_1 = 0;
00387 
00388         lines = 0;
00389 
00390         while (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
00391         {
00392                 if (chatgroup[inc_1] == '\n')
00393                 {
00394                         lines++;
00395                 }
00396                 inc_1++;
00397         }
00398 
00399         if (!lines)
00400         {
00401                 B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
00402                 return 0;
00403         }
00404 
00405         getthisline = Q_irand(0, (lines+1));
00406 
00407         if (getthisline < 1)
00408         {
00409                 getthisline = 1;
00410         }
00411         if (getthisline > lines)
00412         {
00413                 getthisline = lines;
00414         }
00415 
00416         checkedline = 1;
00417 
00418         inc_1 = 0;
00419 
00420         while (checkedline != getthisline)
00421         {
00422                 if (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
00423                 {
00424                         if (chatgroup[inc_1] == '\n')
00425                         {
00426                                 inc_1++;
00427                                 checkedline++;
00428                         }
00429                 }
00430 
00431                 if (checkedline == getthisline)
00432                 {
00433                         break;
00434                 }
00435 
00436                 inc_1++;
00437         }
00438 
00439         //we're at the starting position of the desired line here
00440         inc_2 = 0;
00441 
00442         while (chatgroup[inc_1] != '\n')
00443         {
00444                 chatgroup[inc_2] = chatgroup[inc_1];
00445                 inc_2++;
00446                 inc_1++;
00447         }
00448         chatgroup[inc_2] = '\0';
00449 
00450         //trap_EA_Say(bs->client, chatgroup);
00451         inc_1 = 0;
00452         inc_2 = 0;
00453 
00454         if (strlen(chatgroup) > MAX_CHAT_LINE_SIZE)
00455         {
00456                 B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
00457                 return 0;
00458         }
00459 
00460         while (chatgroup[inc_1])
00461         {
00462                 if (chatgroup[inc_1] == '%' && chatgroup[inc_1+1] != '%')
00463                 {
00464                         inc_1++;
00465 
00466                         if (chatgroup[inc_1] == 's' && bs->chatObject)
00467                         {
00468                                 cobject = bs->chatObject;
00469                         }
00470                         else if (chatgroup[inc_1] == 'a' && bs->chatAltObject)
00471                         {
00472                                 cobject = bs->chatAltObject;
00473                         }
00474                         else
00475                         {
00476                                 cobject = NULL;
00477                         }
00478 
00479                         if (cobject && cobject->client)
00480                         {
00481                                 inc_n = 0;
00482 
00483                                 while (cobject->client->pers.netname[inc_n])
00484                                 {
00485                                         bs->currentChat[inc_2] = cobject->client->pers.netname[inc_n];
00486                                         inc_2++;
00487                                         inc_n++;
00488                                 }
00489                                 inc_2--; //to make up for the auto-increment below
00490                         }
00491                 }
00492                 else
00493                 {
00494                         bs->currentChat[inc_2] = chatgroup[inc_1];
00495                 }
00496                 inc_2++;
00497                 inc_1++;
00498         }
00499         bs->currentChat[inc_2] = '\0';
00500 
00501         if (strcmp(section, "GeneralGreetings") == 0)
00502         {
00503                 bs->doChat = 2;
00504         }
00505         else
00506         {
00507                 bs->doChat = 1;
00508         }
00509         bs->chatTime_stored = (strlen(bs->currentChat)*45)+Q_irand(1300, 1500);
00510         bs->chatTime = level.time + bs->chatTime_stored;
00511 
00512         B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
00513 
00514         return 1;
00515 }
00516 
00517 void ParseEmotionalAttachments(bot_state_t *bs, char *buf)
00518 {
00519         int i = 0;
00520         int i_c = 0;
00521         char tbuf[16];
00522 
00523         while (buf[i] && buf[i] != '}')
00524         {
00525                 while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
00526                 {
00527                         i++;
00528                 }
00529 
00530                 if (buf[i] && buf[i] != '}')
00531                 {
00532                         i_c = 0;
00533                         while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
00534                         {
00535                                 bs->loved[bs->lovednum].name[i_c] = buf[i];
00536                                 i_c++;
00537                                 i++;
00538                         }
00539                         bs->loved[bs->lovednum].name[i_c] = '\0';
00540 
00541                         while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
00542                         {
00543                                 i++;
00544                         }
00545 
00546                         i_c = 0;
00547 
00548                         while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
00549                         {
00550                                 tbuf[i_c] = buf[i];
00551                                 i_c++;
00552                                 i++;
00553                         }
00554                         tbuf[i_c] = '\0';
00555 
00556                         bs->loved[bs->lovednum].level = atoi(tbuf);
00557 
00558                         bs->lovednum++;
00559                 }
00560                 else
00561                 {
00562                         break;
00563                 }
00564 
00565                 if (bs->lovednum >= MAX_LOVED_ONES)
00566                 {
00567                         return;
00568                 }
00569 
00570                 i++;
00571         }
00572 }
00573 
00574 int ReadChatGroups(bot_state_t *bs, char *buf)
00575 {
00576         char *cgroupbegin;
00577         int cgbplace;
00578         int i;
00579 
00580         cgroupbegin = strstr(buf, "BEGIN_CHAT_GROUPS");
00581 
00582         if (!cgroupbegin)
00583         {
00584                 return 0;
00585         }
00586 
00587         if (strlen(cgroupbegin) >= MAX_CHAT_BUFFER_SIZE)
00588         {
00589                 G_Printf(S_COLOR_RED "Error: Personality chat section exceeds max size\n");
00590                 return 0;
00591         }
00592 
00593         cgbplace = cgroupbegin - buf+1;
00594 
00595         while (buf[cgbplace] != '\n')
00596         {
00597                 cgbplace++;
00598         }
00599 
00600         i = 0;
00601 
00602         while (buf[cgbplace] && buf[cgbplace] != '\0')
00603         {
00604                 gBotChatBuffer[bs->client][i] = buf[cgbplace];
00605                 i++;
00606                 cgbplace++;
00607         }
00608 
00609         gBotChatBuffer[bs->client][i] = '\0';
00610 
00611         return 1;
00612 }
00613 
00614 void BotUtilizePersonality(bot_state_t *bs)
00615 {
00616         fileHandle_t f;
00617         int len, rlen;
00618         int failed;
00619         int i;
00620         //char buf[131072];
00621         char *buf = (char *)B_TempAlloc(131072);
00622         char *readbuf, *group;
00623 
00624         len = trap_FS_FOpenFile(bs->settings.personalityfile, &f, FS_READ);
00625 
00626         failed = 0;
00627 
00628         if (!f)
00629         {
00630                 G_Printf(S_COLOR_RED "Error: Specified personality not found\n");
00631                 B_TempFree(131072); //buf
00632                 return;
00633         }
00634 
00635         if (len >= 131072)
00636         {
00637                 G_Printf(S_COLOR_RED "Personality file exceeds maximum length\n");
00638                 B_TempFree(131072); //buf
00639                 return;
00640         }
00641 
00642         trap_FS_Read(buf, len, f);
00643 
00644         rlen = len;
00645 
00646         while (len < 131072)
00647         { //kill all characters after the file length, since sometimes FS_Read doesn't do that entirely (or so it seems)
00648                 buf[len] = '\0';
00649                 len++;
00650         }
00651 
00652         len = rlen;
00653 
00654         readbuf = (char *)B_TempAlloc(1024);
00655         group = (char *)B_TempAlloc(65536);
00656 
00657         if (!GetValueGroup(buf, "GeneralBotInfo", group))
00658         {
00659                 G_Printf(S_COLOR_RED "Personality file contains no GeneralBotInfo group\n");
00660                 failed = 1; //set failed so we know to set everything to default values
00661         }
00662 
00663         if (!failed && GetPairedValue(group, "reflex", readbuf))
00664         {
00665                 bs->skills.reflex = atoi(readbuf);
00666         }
00667         else
00668         {
00669                 bs->skills.reflex = 100; //default
00670         }
00671 
00672         if (!failed && GetPairedValue(group, "accuracy", readbuf))
00673         {
00674                 bs->skills.accuracy = atof(readbuf);
00675         }
00676         else
00677         {
00678                 bs->skills.accuracy = 10; //default
00679         }
00680 
00681         if (!failed && GetPairedValue(group, "turnspeed", readbuf))
00682         {
00683                 bs->skills.turnspeed = atof(readbuf);
00684         }
00685         else
00686         {
00687                 bs->skills.turnspeed = 0.01f; //default
00688         }
00689 
00690         if (!failed && GetPairedValue(group, "turnspeed_combat", readbuf))
00691         {
00692                 bs->skills.turnspeed_combat = atof(readbuf);
00693         }
00694         else
00695         {
00696                 bs->skills.turnspeed_combat = 0.05f; //default
00697         }
00698 
00699         if (!failed && GetPairedValue(group, "maxturn", readbuf))
00700         {
00701                 bs->skills.maxturn = atof(readbuf);
00702         }
00703         else
00704         {
00705                 bs->skills.maxturn = 360; //default
00706         }
00707 
00708         if (!failed && GetPairedValue(group, "perfectaim", readbuf))
00709         {
00710                 bs->skills.perfectaim = atoi(readbuf);
00711         }
00712         else
00713         {
00714                 bs->skills.perfectaim = 0; //default
00715         }
00716 
00717         if (!failed && GetPairedValue(group, "chatability", readbuf))
00718         {
00719                 bs->canChat = atoi(readbuf);
00720         }
00721         else
00722         {
00723                 bs->canChat = 0; //default
00724         }
00725 
00726         if (!failed && GetPairedValue(group, "chatfrequency", readbuf))
00727         {
00728                 bs->chatFrequency = atoi(readbuf);
00729         }
00730         else
00731         {
00732                 bs->chatFrequency = 5; //default
00733         }
00734 
00735         if (!failed && GetPairedValue(group, "hatelevel", readbuf))
00736         {
00737                 bs->loved_death_thresh = atoi(readbuf);
00738         }
00739         else
00740         {
00741                 bs->loved_death_thresh = 3; //default
00742         }
00743 
00744         if (!failed && GetPairedValue(group, "camper", readbuf))
00745         {
00746                 bs->isCamper = atoi(readbuf);
00747         }
00748         else
00749         {
00750                 bs->isCamper = 0; //default
00751         }
00752 
00753         if (!failed && GetPairedValue(group, "saberspecialist", readbuf))
00754         {
00755                 bs->saberSpecialist = atoi(readbuf);
00756         }
00757         else
00758         {
00759                 bs->saberSpecialist = 0; //default
00760         }
00761 
00762         if (!failed && GetPairedValue(group, "forceinfo", readbuf))
00763         {
00764                 Com_sprintf(bs->forceinfo, sizeof(bs->forceinfo), "%s\0", readbuf);
00765         }
00766         else
00767         {
00768                 Com_sprintf(bs->forceinfo, sizeof(bs->forceinfo), "%s\0", DEFAULT_FORCEPOWERS);
00769         }
00770 
00771         i = 0;
00772 
00773         while (i < MAX_CHAT_BUFFER_SIZE)
00774         { //clear out the chat buffer for this bot
00775                 gBotChatBuffer[bs->client][i] = '\0';
00776                 i++;
00777         }
00778 
00779         if (bs->canChat)
00780         {
00781                 if (!ReadChatGroups(bs, buf))
00782                 {
00783                         bs->canChat = 0;
00784                 }
00785         }
00786 
00787         if (GetValueGroup(buf, "BotWeaponWeights", group))
00788         {
00789                 if (GetPairedValue(group, "WP_STUN_BATON", readbuf))
00790                 {
00791                         bs->botWeaponWeights[WP_STUN_BATON] = atoi(readbuf);
00792                         bs->botWeaponWeights[WP_MELEE] = bs->botWeaponWeights[WP_STUN_BATON];
00793                 }
00794 
00795                 if (GetPairedValue(group, "WP_SABER", readbuf))
00796                 {
00797                         bs->botWeaponWeights[WP_SABER] = atoi(readbuf);
00798                 }
00799 
00800                 if (GetPairedValue(group, "WP_BRYAR_PISTOL", readbuf))
00801                 {
00802                         bs->botWeaponWeights[WP_BRYAR_PISTOL] = atoi(readbuf);
00803                 }
00804 
00805                 if (GetPairedValue(group, "WP_BLASTER", readbuf))
00806                 {
00807                         bs->botWeaponWeights[WP_BLASTER] = atoi(readbuf);
00808                 }
00809 
00810                 if (GetPairedValue(group, "WP_DISRUPTOR", readbuf))
00811                 {
00812                         bs->botWeaponWeights[WP_DISRUPTOR] = atoi(readbuf);
00813                 }
00814 
00815                 if (GetPairedValue(group, "WP_BOWCASTER", readbuf))
00816                 {
00817                         bs->botWeaponWeights[WP_BOWCASTER] = atoi(readbuf);
00818                 }
00819 
00820                 if (GetPairedValue(group, "WP_REPEATER", readbuf))
00821                 {
00822                         bs->botWeaponWeights[WP_REPEATER] = atoi(readbuf);
00823                 }
00824 
00825                 if (GetPairedValue(group, "WP_DEMP2", readbuf))
00826                 {
00827                         bs->botWeaponWeights[WP_DEMP2] = atoi(readbuf);
00828                 }
00829 
00830                 if (GetPairedValue(group, "WP_FLECHETTE", readbuf))
00831                 {
00832                         bs->botWeaponWeights[WP_FLECHETTE] = atoi(readbuf);
00833                 }
00834 
00835                 if (GetPairedValue(group, "WP_ROCKET_LAUNCHER", readbuf))
00836                 {
00837                         bs->botWeaponWeights[WP_ROCKET_LAUNCHER] = atoi(readbuf);
00838                 }
00839 
00840                 if (GetPairedValue(group, "WP_THERMAL", readbuf))
00841                 {
00842                         bs->botWeaponWeights[WP_THERMAL] = atoi(readbuf);
00843                 }
00844 
00845                 if (GetPairedValue(group, "WP_TRIP_MINE", readbuf))
00846                 {
00847                         bs->botWeaponWeights[WP_TRIP_MINE] = atoi(readbuf);
00848                 }
00849 
00850                 if (GetPairedValue(group, "WP_DET_PACK", readbuf))
00851                 {
00852                         bs->botWeaponWeights[WP_DET_PACK] = atoi(readbuf);
00853                 }
00854         }
00855 
00856         bs->lovednum = 0;
00857 
00858         if (GetValueGroup(buf, "EmotionalAttachments", group))
00859         {
00860                 ParseEmotionalAttachments(bs, group);
00861         }
00862 
00863         B_TempFree(131072); //buf
00864         B_TempFree(1024); //readbuf
00865         B_TempFree(65536); //group
00866         trap_FS_FCloseFile(f);
00867 }