// DragonBall Arena 2 has been written by: // Matt Brown (Antor), arkaine@sympatico.ca, 2000-2002 // Please follow all previous licenses. Enjoy! #include <sys/types.h> #include <stdio.h> #include <string.h> #include "merc.h" #include "recycle.h" #include "tables.h" #include "olc.h" #include "db.h" #include "rand.h" // **Locals** RoomData *AddRoom args ( ( int nX, int nY, MapData *pMap ) ); char *GenRoomDescr args ( ( ) ); int GetRandMobVnum args ( ( int nDiffLow, int nDiffHigh ) ); void CreateMap args ( ( int nMapVnum, MapData *pMap ) ); RoomData *Dig args ( ( RoomData *pRoom, int nDir, int nState, MapData *pMap ) ); AREA_DATA *GenerateRandArea args ( ( int nVnumLow, int nDiffLow, int nDiffHigh ) ); void AddWpnSpec args ( ( OBJ_DATA *pObj, WpnEffectData *pEffect, WpnSpecData *pSpec ) ); // Prototypes from mem.c AREA_DATA *new_area args ( ( void ) ); EXIT_DATA *new_exit args ( ( void ) ); ROOM_INDEX_DATA *new_room_index args ( ( void ) ); // ie north is (0,-1) relative to a position (1 up), east (1,0) (1 right) int nExitDirEW[6] = {0,1,0,-1,0,0}; int nExitDirNS[6] = {-1,0,1,0,0,0}; // Opposite directions for each direction int nOppDir[6] = {DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP}; #define DESCR_COUNT 12 DescrData ForestDescr[] = { {6, "There is a %s here, %s.", {"stone", "boulder", "tombstone"}, {"covered with moss","littered with bones","cracked asunder"}, {"","",""}}, {5, "A %s %s tree launches towards the sky, %s.", {"small", "large", "massive"}, {"oak", "maple", "pine"}, {"casting deep shadows", "covering the ground with leaves", "offering solace from the sun"}}, {2, "%s footprints run through a patch of %s, evidence of a recent %s.", {"Fox", "Deer", "Boar"}, {"sand", "mud", "dirt"}, {"hunt", "rainfall", "expedition"}}, {2, "A %s spring %s %s, offering water to thirsty passerbys.", {"small, crystalline", "large", "beautiful"}, {"erupts", "trickles", "flows"}, {"from under a tree", "out of a rock", "into a pool"}}, {3, "Birds %s in the %s %s.", {"chirp", "sing", "flutter"}, {"nearby", "surrounding", "immense"}, {"trees", "foliage", "grass"}}, {1, "Bloods %s on a %s, %s.", {"lays splattered", "lays speckled", "flows down"}, {"rock", "tree", "trunk"}, {"indicating a recent battle", "signs of a fight", "the remains of an unfortunate victim"}}, {3, "A %s, %s %s sits off in the woods.", {"split", "decaying", "rotten"}, {"ancient", "newly-fallen", "bare"}, {"tree", "tree trunk", "branch"}}, {1, "A%s skull is %s on a %s, warding off visitors.", {"n icerian", " saiya-jin", " human"}, {"impaled", "ruthelessly stuck", "smashed onto"}, {"pike", "spear", "stick"}}, {1, "A monument of Antor is erected here. He flexes his muscles, showing off his godly powers. Obviously, he is quite strong.", {"","",""},{"","",""},{"","",""}}, {8, "Sunlight %s the %s, highlighting %s.", {"filters through", "plays amidst", "beams through"}, {"overhead branches", "foliage", "high-reaching trees"}, {"various flowers on the forest flower", "animals playing in the leaves", "cast aside stones and pebbles"}}, {4, "%s can heard from deep within.", {"Chattering", "Rustling", "Singing"}, {"","",""}, {"","",""}}, {8, "The %s continues, %s and %s.", {"path", "trail", "walk"}, {"although it is quite muddy", "torn apart by many feet", "marked with flagstones"}, {"covered by many small twigs", "littered with cast-aside garbage", "encroached upon by many persistant weeds"}}, {0, "", {"","",""}, {"","",""}, {"","",""}} // Dont include in DESCR_COUNT }; RoomData *room_free = NULL; RoomData *new_room (void) { static RoomData room_zero; RoomData *room; if (room_free == NULL) room = alloc_perm (sizeof (*room)); else { room = room_free; room_free = room_free->pNext; } *room = room_zero; VALIDATE (room); return room; } void free_room (RoomData * room){ if (!IS_VALID (room)) return; INVALIDATE (room); room->pNext = room_free; room_free = room; } RoomData *AddRoom (int nX, int nY, MapData *pMap) { RoomData *pNewRoom; int i; pNewRoom = new_room(); pNewRoom->nX = nX; pNewRoom->nY = nY; pNewRoom->nNumber = pMap->nRoomCount; ++pMap->nRoomCount; pMap->pRoomGrid[nX][nY] = pNewRoom; for (i = 0; i < 6; ++i) pNewRoom->pExit[i] = NULL; pNewRoom->pRoomIndex = NULL; pNewRoom->pNextProcess = NULL; pNewRoom->nState = 0; pNewRoom->nMobDiff = 0; pNewRoom->pNext = pMap->pTopRoom; pMap->pTopRoom = pNewRoom; return pNewRoom; } char *GenRoomDescr (DescrData *pDescr) { char szBuf[MAX_STRING_LENGTH]; int nLastLine = -1, nLineCount = 0; //DescrData *pDescr = ForestDescr; szBuf[0] = '\0'; while (nLineCount < 2) { int nLine = 0;//, nLineNum = 0, nChance, nCur = 0; int nArg; char szArg1[40], szArg2[40], szArg3[40]; // Find the line to use /* while (TRUE) { if (pDescr[nCur].szLine[0] == '\0') // Last line break; else if ((nChance = number_range(1,1000)) > nLineNum) { nLineNum = nChance; nLine = nCur; nCur++; } } */ do { nLine = number_range(0,DESCR_COUNT-1); if (number_range(1,10) > pDescr[nLine].nWeight) nLine = nLastLine; } while (nLine == nLastLine); if (nLastLine == -1) nLastLine = nLine; ++nLineCount; // Find the args szArg1[0] = '\0'; szArg2[0] = '\0'; szArg3[0] = '\0'; while (pDescr[nLine].szOption1[0][0] != '\0') { // Make sure there is actually an option nArg = number_range(0,2); if (pDescr[nLine].szOption1[nArg][0] == '\0') continue; strcpy (szArg1, pDescr[nLine].szOption1[nArg]); break; } while (pDescr[nLine].szOption2[0][0] != '\0') { nArg = number_range(0,2); if (pDescr[nLine].szOption2[nArg][0] == '\0') continue; strcpy (szArg2, pDescr[nLine].szOption2[nArg]); break; } while (pDescr[nLine].szOption3[0][0] != '\0') { nArg = number_range(0,2); if (pDescr[nLine].szOption3[nArg][0] == '\0') continue; strcpy (szArg3, pDescr[nLine].szOption3[nArg]); break; } if (szArg1[0] == '\0') sprintf (szBuf+strlen(szBuf), pDescr[nLine].szLine); else if (szArg2[0] == '\0') sprintf (szBuf+strlen(szBuf), pDescr[nLine].szLine, szArg1); else if (szArg3[0] == '\0') sprintf (szBuf+strlen(szBuf), pDescr[nLine].szLine, szArg1, szArg2); else sprintf (szBuf+strlen(szBuf), pDescr[nLine].szLine, szArg1, szArg2, szArg3); } return (format_string(str_dup(szBuf))); } int GetRandMobVnum (int nDiffLow, int nDiffHigh) { CHAR_DATA *target = NULL; CHAR_DATA *pCreated = NULL; MOB_INDEX_DATA *pIndex; int nVnum, nCount = 0; MOB_INDEX_DATA *pList[250]; // Populate the list for (nVnum = 0; nVnum < top_vnum_mob; ++nVnum) { if ((pIndex = get_mob_index (nVnum)) == NULL) continue; if (!pIndex->pCreated) // No mobs of this vnum loaded pCreated = create_mobile (pIndex); target = pIndex->pCreated; if (//IS_NPC(target)AL(target) || (ch->alignment > 0 ? IS_EVIL(target) : IS_GOOD(target))) target->nDifficulty >= nDiffLow && target->nDifficulty <= nDiffHigh && !IS_SET(target->act, ACT_IS_HEALER) && !IS_SET(target->act, ACT_IS_CHANGER) && !IS_SET(target->imm_flags, IMM_SUMMON) && !IS_SET(target->affected_by, AFF_CHARM) && target->pIndexData->mprogs == NULL) { if (nCount >= 250) pList[number_range(0,249)] = pIndex; else pList[nCount++] = pIndex; } if (pCreated) { extract_char (pCreated, TRUE); pCreated = NULL; } } if (nCount == 0) return (0); pIndex = pList[number_range(0, nCount - 1)]; // Random index return (pIndex->vnum); } void CreateMap (int nMapVnum, MapData *pMap) { int nXLower, nXUpper, nYLower, nYUpper, x, y; char buf[MAX_STRING_LENGTH]; RoomData *pCur; OBJ_INDEX_DATA *pMapObj; bool bBreak; pMapObj = get_obj_index(nMapVnum); // Trim it down bBreak = FALSE; for (nYLower = 0; nYLower < GRIDSIZE; ++nYLower) { for (x = 0; x < GRIDSIZE; ++x) { if (pMap->pRoomGrid[x][nYLower] != NULL) { bBreak = TRUE; break; } } if (bBreak) break; } bBreak = FALSE; for (nYUpper = GRIDSIZE-1; nYUpper >= 0; --nYUpper) { for (x = 0; x < GRIDSIZE; ++x) { if (pMap->pRoomGrid[x][nYUpper] != NULL) { bBreak = TRUE; break; } } if (bBreak) break; } bBreak = FALSE; for (nXLower = 0; nXLower < GRIDSIZE; ++nXLower) { for (y = 0; y < GRIDSIZE; ++y) { if (pMap->pRoomGrid[nXLower][y] != NULL) { bBreak = TRUE; break; } } if (bBreak) break; } bBreak = FALSE; for (nXUpper = GRIDSIZE-1; nXUpper >= 0; --nXUpper) { for (y = 0; y < GRIDSIZE; ++y) { if (pMap->pRoomGrid[nXUpper][y] != NULL) { bBreak = TRUE; break; } } if (bBreak) break; } strcpy (buf, "{x"); for (y = nYLower; y <= nYUpper; ++y) { for (x = nXLower; x <= nXUpper; ++x) { if ((pCur = pMap->pRoomGrid[x][y]) == NULL) strcat (buf, " "); else if (pCur->pExit[DIR_NORTH]) strcat (buf, " |"); else strcat (buf, " "); } strcat (buf, "\n\r"); for (x = nXLower; x <= nXUpper; ++x) { if ((pCur = pMap->pRoomGrid[x][y]) == NULL) strcat (buf, " "); else if (pCur->pExit[DIR_WEST]) strcat (buf, (x == GRIDSIZE/2 && y == GRIDSIZE/2) ? "-{RC{x" : "-O"); else strcat (buf, (x == GRIDSIZE/2 && y == GRIDSIZE/2) ? " {RC{x" : " O"); } strcat (buf, "\n\r"); } free_string (pMapObj->description); pMapObj->description = str_dup (buf); } // Tries to add a room from a specified room out in a direction RoomData *Dig (RoomData *pRoom, int nDir, int nState, MapData *pMap) { RoomData *pDest; // Check if we go off the bounds of the grid if (pRoom->nX + nExitDirEW[nDir] < 0 || pRoom->nX + nExitDirEW[nDir] > GRIDSIZE - 1) return NULL; else if (pRoom->nY + nExitDirNS[nDir] < 0 || pRoom->nY + nExitDirNS[nDir] > GRIDSIZE - 1) return NULL; if ((pDest = pMap->pRoomGrid[pRoom->nX + nExitDirEW[nDir]][pRoom->nY + nExitDirNS[nDir]])) { // Connect anyways? if (number_chance(50)) return NULL; pRoom->pExit[nDir] = pDest; pDest->pExit[nOppDir[nDir]] = pRoom; } else { pDest = AddRoom (pRoom->nX + nExitDirEW[nDir], pRoom->nY + nExitDirNS[nDir], pMap); pDest->nState = nState; pDest->nMobDiff = pRoom->nMobDiff + (number_range(1,5) == 1 ? 2 : 0); // Link exits pRoom->pExit[nDir] = pDest; pDest->pExit[nOppDir[nDir]] = pRoom; // Add to the list of rooms to process if (pMap->pProcessLast != NULL) pMap->pProcessLast->pNextProcess = pDest; else pMap->pProcess = pDest; pMap->pProcessLast = pDest; } return pDest; } #define CHANCE_FUZZ (map.nRoomCount < 25 ? 3 : 1) //((nMaxRooms - 2*map.nRoomCount) / 10) ShapeData dungeon = {15, 15, 35, 75, 0}; ShapeData forest = {1, 1, 0, 100, 10}; AREA_DATA *GenerateRandArea (int nVnumLow, int nDiffLow, int nDiffHigh) { MapData map; //RoomData *pRoomGrid[GRIDSIZE][GRIDSIZE]; //RoomData *pTopRoom = NULL; //int nRoomCount = 0; AREA_DATA *pArea; RoomData *pCur, *pNext;//, *pProcess, *pProcessLast; int nMaxRooms = number_range(1000, 1999), nExit, x, y; ShapeData *pExitChance = &forest; map.nRoomCount = 0; map.pTopRoom = NULL; // Clear out the grid for (y = 0; y < GRIDSIZE; ++y) for (x = 0; x < GRIDSIZE; ++x) map.pRoomGrid[x][y] = NULL; // Start with a single room map.pProcess = AddRoom(GRIDSIZE/2,GRIDSIZE/2, &map); do map.pProcess->nState = number_range(FIRST_STATE, LAST_STATE); while (map.pProcess->nState == ROOM); map.pProcess->nMobDiff = 10; map.pProcessLast = map.pProcess; // Now go through the process list while ((pCur = map.pProcess) && map.nRoomCount < nMaxRooms) { map.pProcess = map.pProcess->pNextProcess; if (map.pProcess == NULL) map.pProcessLast = NULL; // have arrays with different sets of values for each chance, // depending on land type if (pCur->nState == HALL_N || pCur->nState == HALL_NS) { if (number_chance(pExitChance->nFourway*CHANCE_FUZZ)) Dig (pCur, DIR_NORTH, HALL_IN, &map); else if (number_chance(pExitChance->nIntersection*CHANCE_FUZZ)) Dig (pCur, DIR_NORTH, HALL_EW, &map); else if (number_chance(pExitChance->nRoom) && map.nRoomCount >= 25) Dig (pCur, DIR_NORTH, ROOM, &map); else if (number_chance(pExitChance->nWinding*CHANCE_FUZZ)) Dig (pCur, number_chance(50) ? DIR_WEST : DIR_EAST, HALL_N, &map); else if (number_chance(pExitChance->nContinue*CHANCE_FUZZ)) Dig (pCur, DIR_NORTH, HALL_NS, &map); } if (pCur->nState == HALL_E || pCur->nState == HALL_EW) { if (number_chance(pExitChance->nFourway*CHANCE_FUZZ)) Dig (pCur, DIR_EAST, HALL_IN, &map); else if (number_chance(pExitChance->nIntersection*CHANCE_FUZZ)) Dig (pCur, DIR_EAST, HALL_NS, &map); else if (number_chance(pExitChance->nRoom) && map.nRoomCount >= 25) Dig (pCur, DIR_EAST, ROOM, &map); else if (number_chance(pExitChance->nWinding*CHANCE_FUZZ)) Dig (pCur, number_chance(50) ? DIR_NORTH : DIR_SOUTH, HALL_E, &map); else if (number_chance(pExitChance->nContinue*CHANCE_FUZZ)) Dig (pCur, DIR_EAST, HALL_EW, &map); } if (pCur->nState == HALL_S || pCur->nState == HALL_NS) { if (number_chance(pExitChance->nFourway*CHANCE_FUZZ)) Dig (pCur, DIR_SOUTH, HALL_IN, &map); else if (number_chance(pExitChance->nIntersection*CHANCE_FUZZ)) Dig (pCur, DIR_SOUTH, HALL_EW, &map); else if (number_chance(pExitChance->nRoom) && map.nRoomCount >= 25) Dig (pCur, DIR_SOUTH, ROOM, &map); else if (number_chance(pExitChance->nWinding*CHANCE_FUZZ)) Dig (pCur, number_chance(50) ? DIR_WEST : DIR_EAST, HALL_S, &map); else if (number_chance(pExitChance->nContinue*CHANCE_FUZZ)) Dig (pCur, DIR_SOUTH, HALL_NS, &map); } if (pCur->nState == HALL_W || pCur->nState == HALL_EW) { if (number_chance(pExitChance->nFourway*CHANCE_FUZZ)) Dig (pCur, DIR_WEST, HALL_IN, &map); else if (number_chance(pExitChance->nIntersection*CHANCE_FUZZ)) Dig (pCur, DIR_WEST, HALL_NS, &map); else if (number_chance(pExitChance->nRoom) && map.nRoomCount >= 25) Dig (pCur, DIR_WEST, ROOM, &map); else if (number_chance(pExitChance->nWinding*CHANCE_FUZZ)) Dig (pCur, number_chance(50) ? DIR_NORTH : DIR_SOUTH, HALL_W, &map); else if (number_chance(pExitChance->nContinue*CHANCE_FUZZ)) Dig (pCur, DIR_WEST, HALL_EW, &map); } if (pCur->nState == HALL_IN) { Dig (pCur, DIR_NORTH, HALL_NS, &map); Dig (pCur, DIR_SOUTH, HALL_NS, &map); Dig (pCur, DIR_EAST, HALL_EW, &map); Dig (pCur, DIR_WEST, HALL_EW, &map); } /* case ROOM: if (number_chance(20*CHANCE_FUZZ)) Dig (pCur, DIR_NORTH, number_chance(25) ? ROOM : HALL_NS, &map); if (number_chance(20*CHANCE_FUZZ)) Dig (pCur, DIR_SOUTH, number_chance(25) ? ROOM : HALL_NS, &map); if (number_chance(20*CHANCE_FUZZ)) Dig (pCur, DIR_EAST, number_chance(25) ? ROOM : HALL_EW, &map); if (number_chance(20*CHANCE_FUZZ)) Dig (pCur, DIR_WEST, number_chance(25) ? ROOM : HALL_EW, &map); break;*/ } // Now convert this prototype to an actual in-game area { ROOM_INDEX_DATA *pRoom; ROOM_INDEX_DATA *toRoom; EXIT_DATA *pExit; RESET_DATA *pReset; int iHash, i, nMobCount; //int nMob1 = 0, nMob2 = 0, nMob3 = 0; int nMobVnumList[15][3]; for (i = 0; i < 15; ++i) { nMobVnumList[i][1] = GetRandMobVnum(i * 150, (i+1) * 150); nMobVnumList[i][2] = GetRandMobVnum(i * 150, (i+1) * 150); nMobVnumList[i][3] = GetRandMobVnum(i * 150, (i+1) * 150); } // Pick three different mobs to populate the area with //nMob1 = GetRandMobVnum(nDiffLow,nDiffHigh); //nMob2 = GetRandMobVnum(nDiffLow,nDiffHigh); //nMob3 = GetRandMobVnum(nDiffLow,nDiffHigh); pArea = new_area (); area_last->next = pArea; area_last = pArea; pArea->name = str_dup ("Random Realm"); pArea->credits = str_dup ("The cOmPuTeR"); pArea->file_name = str_dup ("rand0000.are"); pArea->area_flags = AREA_DONTSAVE; pArea->min_vnum = nVnumLow; pArea->max_vnum = nVnumLow+map.nRoomCount; // Now create rooms for (pCur = map.pTopRoom; pCur; pCur = pCur->pNext) { pRoom = new_room_index (); pRoom->area = pArea; pRoom->vnum = nVnumLow + pCur->nNumber; pRoom->description = GenRoomDescr(ForestDescr); pCur->pRoomIndex = pRoom; // For ease of linkage if (pRoom->vnum > top_vnum_room) top_vnum_room = pRoom->vnum; iHash = pRoom->vnum % MAX_KEY_HASH; pRoom->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoom; // Add a mob reset if (nMobVnumList[UMIN(15,pCur->nMobDiff/150)][1] != 0) { nMobCount = number_range(1, 25); if (nMobCount == 25) nMobCount = 5; else if (nMobCount >= 23) nMobCount = 4; else if (nMobCount >= 21) nMobCount = 3; else if (nMobCount >= 16) nMobCount = 2; else nMobCount = 1; for (i = 0; i < nMobCount; ++i) { pReset = new_reset_data (); pReset->command = 'M'; pReset->arg1 = number_range(1,10); if (pReset->arg1 == 10 && nMobVnumList[UMIN(15,pCur->nMobDiff/150)][3] != 0) pReset->arg1 = nMobVnumList[UMIN(15,pCur->nMobDiff/150)][3]; else if (pReset->arg1 >= 7 && nMobVnumList[UMIN(15,pCur->nMobDiff/150)][2] != 0) pReset->arg1 = nMobVnumList[UMIN(15,pCur->nMobDiff/150)][2]; else pReset->arg1 = nMobVnumList[UMIN(15,pCur->nMobDiff/150)][1]; pReset->arg2 = 100; pReset->arg3 = pRoom->vnum; pReset->arg4 = 3; // number in room add_reset (pRoom, pReset, 0); } } } // Link the rooms for (pCur = map.pTopRoom; pCur; pCur = pCur->pNext) { pRoom = pCur->pRoomIndex; for (nExit = 0; nExit < 6; ++nExit) { // No exit if (pCur->pExit[nExit] == NULL) continue; if ((toRoom = pCur->pExit[nExit]->pRoomIndex) == NULL) continue; // Other side's exit already exists if (toRoom->exit[nOppDir[nExit]]) continue; if (!pRoom->exit[nExit]) pRoom->exit[nExit] = new_exit (); pRoom->exit[nExit]->u1.to_room = toRoom; pRoom->exit[nExit]->orig_door = nExit; nExit = nOppDir[nExit]; pExit = new_exit (); pExit->u1.to_room = pRoom; pExit->orig_door = nExit; toRoom->exit[nExit] = pExit; } } } // Create some standard items { OBJ_INDEX_DATA *pObj; RESET_DATA *pReset; int iHash; // The Map pObj = new_obj_index (); iHash = nVnumLow % MAX_KEY_HASH; pObj->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObj; pObj->vnum = nVnumLow; pObj->area = pArea; pObj->reset_num = 0; pObj->name = str_dup("map"); pObj->short_descr = str_dup("A Map"); pObj->description = str_dup("This is the map"); pObj->material = str_dup("paper"); pObj->durability = 1; pObj->item_type = ITEM_TRASH; pObj->extra_flags = 0; pObj->wear_flags = ITEM_TAKE|ITEM_HOLD; pObj->value[0] = 0; pObj->value[1] = 0; pObj->value[2] = 0; pObj->value[3] = 0; pObj->value[4] = 0; pObj->llPl = 1; pObj->weight = 1; pObj->cost = 1; CreateMap (nVnumLow, &map); // The Portal Out pObj = new_obj_index (); iHash = (nVnumLow+1) % MAX_KEY_HASH; pObj->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObj; pObj->vnum = nVnumLow+1; pObj->area = pArea; pObj->reset_num = 0; pObj->name = str_dup("rift"); pObj->short_descr = str_dup("The Rift"); pObj->description = str_dup("The Rift"); pObj->material = str_dup("unknown"); pObj->durability = 1; pObj->item_type = ITEM_PORTAL; pObj->extra_flags = ITEM_NOPURGE; pObj->wear_flags = 0; pObj->value[0] = 0; pObj->value[1] = 0; pObj->value[2] = 0; pObj->value[3] = 201; pObj->value[4] = 0; pObj->llPl = 1; pObj->weight = 1; pObj->cost = 1; // Add to the starting room pReset = new_reset_data (); pReset->command = 'O'; pReset->arg1 = nVnumLow+1; pReset->arg2 = 0; pReset->arg3 = nVnumLow; pReset->arg4 = 0; add_reset (get_room_index(nVnumLow), pReset, 0); if (nVnumLow+1 > top_vnum_obj) top_vnum_obj = nVnumLow+1; newobjs += 2; } // Delete the prototype rooms for (pCur = map.pTopRoom; pCur; pCur = pNext) { pNext = pCur->pNext; free_room (pCur); } map.pTopRoom = NULL; for (y = 0; y < GRIDSIZE; ++y) for (x = 0; x < GRIDSIZE; ++x) map.pRoomGrid[x][y] = NULL; map.nRoomCount = 0; return (pArea); } void GenerateVoid () { int i, nLastVnum = VNUM_RANDOM_LOW-1; AREA_DATA *pArea, *pLastArea = NULL; ROOM_INDEX_DATA *pRoom1, *pRoom2; for (i = 0; i < 1; ++i) { pArea = GenerateRandArea (nLastVnum+1, i * 150, (i+1) * 150); // Link the two areas if (pLastArea != NULL) { // Pick one in the last half of the vnums pRoom1 = get_room_index(number_range((pArea->max_vnum - pArea->min_vnum) / 2 + pArea->min_vnum, pArea->max_vnum)); pRoom2 = get_room_index(number_range((pLastArea->max_vnum - pLastArea->min_vnum) / 2 + pLastArea->min_vnum, pLastArea->max_vnum)); // Exit up pRoom1->exit[4] = new_exit (); pRoom1->exit[4]->u1.to_room = pRoom2; pRoom1->exit[4]->orig_door = 4; // Exit down pRoom2->exit[5] = new_exit (); pRoom2->exit[5]->u1.to_room = pRoom1; pRoom2->exit[5]->orig_door = 5; } reset_area (pArea); nLastVnum = pArea->max_vnum; pLastArea = pArea; } } // Base weapon types BaseWeaponData BaseWpnTable[BASEITEM_COUNT] = { // {"name list", "name", "on ground name", "material", weight, cost, class, low_dam, high_dam, dam_type {"dagger", "dagger", "A dagger sits here.", "steel", 20, 1, WEAPON_DAGGER, 1, 6, "pierce"}, {"shortsword sword", "shortsword", "A shortsword sits here.", "steel", 50, 4, WEAPON_SWORD, 1, 8, "stab"}, {"longsword sword", "longsword", "A longsword sits here.", "steel", 125, 10, WEAPON_SWORD, 1, 12, "slash"}, {"katana", "katana", "A katana collects dust.", "steel", 150, 85, WEAPON_SWORD, 2, 14, "cleave"}, {"club", "club", "A primitive club lies around.", "wood", 30, 1, WEAPON_MACE, 1, 8, "crush"}, {"mace", "mace", "A mace is here.", "iron", 100, 10, WEAPON_MACE, 1, 12, "smash"}, {"flail", "flail", "A flail lies in the dirt.", "steel", 150, 15, WEAPON_FLAIL, 3, 12, "twack"}, {"spear", "spear", "A spear sits here.", "steel", 150, 4, WEAPON_SPEAR, 1, 10, "pierce"}, {"staff", "staff", "A staff lies around.", "wood", 100, 1, WEAPON_SPEAR, 1, 8, "pound"}, {"handaxe axe", "handaxe", "A handaxe lies around", "iron", 50, 3, WEAPON_AXE, 1, 8, "chop"}, {"battleaxe axe", "battleaxe", "A battleaxe lies in the dirt.", "steel", 125, 15, WEAPON_AXE, 1, 13, "chop"}, {"irgaak", "irgaak", "An irgaak sits here.", "steel", 300, 100, WEAPON_POLEARM, 2, 20, "slice"} }; // Weapon prefixes. // Sort by level, then rarity -- this is mandatory WpnEffectData WpnPreTable[WPNPRE_COUNT] = { // {"name", "world list", level, rarity, {{location, add/mult, nMod1, nMod2} ...} } {"", "", 0, NORMAL, {{LOC_NONE, ADD, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"sharp", "sharp", 1, NORMAL, {{LOC_DAM, ADD, 1, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"expensive", "expensive", 1, NORMAL, {{LOC_COST, MULT, 5, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"stone", "stone", 1, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 1, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 1, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"massive", "massive", 1, RARE, {{LOC_DAM, ADD, 2, 0, 0, 0}, {LOC_WEIGHT, MULT, 3, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"keen", "keen", 5, NORMAL, {{LOC_DAM, ADD, 2, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"bronze", "bronze", 11, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 2, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 2, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"blessed", "blessed", 10, RARE, {{LOC_EXTRA, NONE, ITEM_BLESS, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"iron", "iron", 21, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 3, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 3, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"steel", "steel", 31, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 4, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 4, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"swift", "swift", 35, RARE, {{LOC_AFFECT, NONE, 0, 0, -1, AFF_HASTE}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"silver", "silver", 41, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 5, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 5, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"gold", "gold", 51, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 6, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 6, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"seeking", "seeking", 50, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 10, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"adamantium", "adamantium", 61, NORMAL, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 7, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 7, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"Heightened", "heightened", 100, UNIQUE, {{LOC_OBJAFF, NONE, APPLY_HITROLL, 25, 0, 0}, {LOC_OBJAFF, NONE, APPLY_DAMROLL, 25, 0, 0}, {LOC_AFFECT, NONE, 0, 0, -1, AFF_HASTE}, {LOC_EXTRA, NONE, ITEM_BLESS|ITEM_HUM, 0, 0, 0}, }} }; // Weapon suffixes. // Also sort by level then rarity (has to be this way) WpnEffectData WpnSufTable[WPNSUF_COUNT] = { {"", "", 0, NORMAL, {{LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of sharpness", "sharpness", 1, NORMAL, {{LOC_DAM, ADD, 1, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of expensiveness", "expensiveness", 1, NORMAL, {{LOC_COST, MULT, 5, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of massiveness", "massiveness", 1, RARE, {{LOC_DAM, ADD, 2, 0, 0, 0}, {LOC_WEIGHT, MULT, 3, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of humming", "humming", 3, RARE, {{LOC_EXTRA, NONE, ITEM_HUM, 0, 0, 0}, {LOC_COST, ADD, 150, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of glowing", "glowing", 3, RARE, {{LOC_EXTRA, NONE, ITEM_GLOW, 0, 0, 0}, {LOC_COST, ADD, 150, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}}, {"of energy", "energy", 10, NORMAL, {{LOC_OBJAFF, NONE, APPLY_KI, 50, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}, {LOC_NONE, NONE, 0, 0, 0, 0}}} }; void AddWpnSpec (OBJ_DATA *pObj, WpnEffectData *pEffect, WpnSpecData *pSpec) { AFFECT_DATA *pAf; switch (pSpec->nLoc) { case LOC_EXTRA: pObj->extra_flags |= pSpec->nMod1; break; case LOC_DAM: if (pSpec->nOperation == ADD) { pObj->value[1] += pSpec->nMod1; pObj->value[2] += pSpec->nMod1; } else { pObj->value[1] *= pSpec->nMod1; pObj->value[2] *= pSpec->nMod1; } break; case LOC_COST: if (pSpec->nOperation == ADD) pObj->cost += pSpec->nMod1; else pObj->cost *= pSpec->nMod1; break; case LOC_WEIGHT: if (pSpec->nOperation == ADD) pObj->weight += pSpec->nMod1; else pObj->weight *= pSpec->nMod1; break; case LOC_DURAB: if (pSpec->nOperation == ADD) pObj->durability += pSpec->nMod1; else pObj->durability *= pSpec->nMod1; break; case LOC_OBJAFF: pAf = new_affect(); pAf->location = pSpec->nMod1; pAf->modifier = pSpec->nMod2; pAf->where = TO_OBJECT; pAf->type = pSpec->nMod3; pAf->duration = -1; pAf->bitvector = pSpec->nMod4; pAf->skill_lvl = pEffect->nLevel; pAf->next = pObj->affected; pObj->affected = pAf; break; case LOC_WPNAFF: pAf = new_affect(); pAf->location = pSpec->nMod1; pAf->modifier = pSpec->nMod2; pAf->where = TO_WEAPON; pAf->type = pSpec->nMod3; pAf->duration = -1; pAf->bitvector = pSpec->nMod4; pAf->skill_lvl = pEffect->nLevel; pAf->next = pObj->affected; pObj->affected = pAf; break; case LOC_AFFECT: pAf = new_affect(); pAf->location = pSpec->nMod1; pAf->modifier = pSpec->nMod2; pAf->where = TO_AFFECTS; pAf->type = pSpec->nMod3; pAf->duration = -1; pAf->bitvector = pSpec->nMod4; pAf->skill_lvl = pEffect->nLevel; pAf->next = pObj->affected; pObj->affected = pAf; break; } } OBJ_DATA *CreateRandWeapon (int nLevel) { OBJ_DATA *pObj; int nWpn; int i, nPrefix; int nSuffix; int nPreCount = 0, nSufCount = 0; char szBuf[MAX_STRING_LENGTH], cLetter; bool bPrefix, bSuffix, bVowel; nWpn = number_range(1, BASEITEM_COUNT) - 1; if (get_obj_index(OBJ_VNUM_RANDOM) == NULL) { logstr (LOG_BUG, "CreateRandWeapon: OBJ_VNUM_RANDOM not found"); return NULL; } pObj = create_object(get_obj_index(OBJ_VNUM_RANDOM), 0); for (i = 0; i < WPNPRE_COUNT; ++i) if (nLevel - WpnPreTable[i].nLevel <= 10 && nLevel - WpnPreTable[i].nLevel >= -10) ++nPreCount; if (nPreCount == 0) nPrefix = 0; else { while (TRUE) { nPrefix = number_range(0, WPNPRE_COUNT-1); if (nLevel - WpnPreTable[nPrefix].nLevel <= 10 && nLevel - WpnPreTable[nPrefix].nLevel >= -10) { if (WpnPreTable[nPrefix].nRarity == NORMAL && number_range (1, 4) < 4) break; else if (WpnPreTable[nPrefix].nRarity == RARE && number_range (1, 5) == 1) break; else if (WpnPreTable[nPrefix].nRarity == UNIQUE && number_range (1, 20) == 1) break; } } } for (i = 0; i < WPNSUF_COUNT; ++i) if (nLevel - WpnSufTable[i].nLevel <= 10 && nLevel - WpnSufTable[i].nLevel >= -10) ++nSufCount; if (nSufCount == 0) nSuffix = 0; else { while (TRUE) { nSuffix = number_range(0, WPNSUF_COUNT-1); if (nLevel - WpnSufTable[nSuffix].nLevel <= 10 && nLevel - WpnSufTable[nSuffix].nLevel >= -10) { if (WpnSufTable[nSuffix].nRarity == NORMAL && number_range (1, 4) < 4) break; else if (WpnSufTable[nSuffix].nRarity == RARE && number_range (1, 5) == 1) break; else if (WpnSufTable[nSuffix].nRarity == UNIQUE && number_range (1, 20) == 1) break; } } } // Create the right name cLetter = WpnPreTable[nPrefix].szName[0]; if (cLetter == '\0') { bPrefix = FALSE; cLetter = BaseWpnTable[nWpn].szBaseName[0]; } else bPrefix = TRUE; if (WpnSufTable[nSuffix].szName[0] == '\0') bSuffix = FALSE; else bSuffix = TRUE; if (cLetter == 'a' || cLetter == 'e' || cLetter == 'i' || cLetter == 'o' || cLetter == 'u') bVowel = TRUE; else bVowel = FALSE; sprintf (szBuf, "a%s %s%s%s%s%s", bVowel ? "n" : "", WpnPreTable[nPrefix].szName, bPrefix ? " " : "", BaseWpnTable[nWpn].szBaseName, bSuffix ? " " : "", WpnSufTable[nSuffix].szName); pObj->short_descr = str_dup(szBuf); strcpy (szBuf, BaseWpnTable[nWpn].szName); if (WpnPreTable[nPrefix].szWordList[0] != '\0') { strcat (szBuf, " "); strcat (szBuf, WpnPreTable[nPrefix].szWordList); } if (WpnSufTable[nSuffix].szWordList[0] != '\0') { strcat (szBuf, " "); strcat (szBuf, WpnSufTable[nSuffix].szWordList); } pObj->name = str_dup(szBuf); pObj->item_type = ITEM_WEAPON; pObj->wear_flags = ITEM_TAKE|ITEM_WIELD; pObj->extra_flags = ITEM_RANDOM; pObj->description = str_dup(BaseWpnTable[nWpn].szLong); pObj->material = str_dup(BaseWpnTable[nWpn].szMaterial); pObj->weight = BaseWpnTable[nWpn].nWeight; pObj->cost = BaseWpnTable[nWpn].nCost; pObj->value[0]= BaseWpnTable[nWpn].nClass; pObj->value[1] = BaseWpnTable[nWpn].nLowDam; pObj->value[2] = BaseWpnTable[nWpn].nHighDam; pObj->value[3] = attack_lookup(BaseWpnTable[nWpn].szDamType); pObj->value[4] = 0; for (i = 0; i < 4; ++i) { AddWpnSpec (pObj, &WpnPreTable[nPrefix], &WpnPreTable[nPrefix].spec[i]); AddWpnSpec (pObj, &WpnSufTable[nSuffix], &WpnSufTable[nSuffix].spec[i]); } return pObj; }