String StyleResolverStats::report() const { StringBuilder output; unsigned sharedStylesRejected = sharedStyleRejectedByAttributeRules; unsigned sharedStylesUsed = sharedStyleFound - sharedStylesRejected; output.appendLiteral("Style sharing:\n"); output.append(String::format(" %u elements were added to the sharing candidate list.\n", sharedStyleCandidates)); output.append(String::format(" %u calls were made to findSharedStyle, %u found a candidate to share with (%.2f%%).\n", sharedStyleLookups, sharedStyleFound, PERCENT(sharedStyleFound, sharedStyleLookups))); if (printMissedCandidateCount) output.append(String::format(" %u candidates could have matched but were not in the list when searching (%.2f%%).\n", sharedStyleMissed, PERCENT(sharedStyleMissed, sharedStyleLookups))); output.append(String::format(" %u of found styles were rejected (%.2f%%), %.2f%% by attribute rules.\n", sharedStylesRejected, PERCENT(sharedStylesRejected, sharedStyleFound), PERCENT(sharedStyleRejectedByAttributeRules, sharedStylesRejected))); output.append(String::format(" %u of found styles were used for sharing (%.2f%%).\n", sharedStylesUsed, PERCENT(sharedStylesUsed, sharedStyleFound))); output.append(String::format(" %.2f%% of calls to findSharedStyle returned a shared style.\n", PERCENT(sharedStylesUsed, sharedStyleLookups))); output.append('\n'); output.appendLiteral("Matched property cache:\n"); output.append(String::format(" %u calls to applyMatchedProperties, %u hit the cache (%.2f%%).\n", matchedPropertyApply, matchedPropertyCacheHit, PERCENT(matchedPropertyCacheHit, matchedPropertyApply))); output.append(String::format(" %u cache hits also shared the inherited style (%.2f%%).\n", matchedPropertyCacheInheritedHit, PERCENT(matchedPropertyCacheInheritedHit, matchedPropertyCacheHit))); output.append(String::format(" %u styles created in applyMatchedProperties were added to the cache (%.2f%%).\n", matchedPropertyCacheAdded, PERCENT(matchedPropertyCacheAdded, matchedPropertyApply))); return output.toString(); }
// --------------------------------------------------------------------- // Selects all damaged units - on screen toggle. UDWORD selSelectAllDamaged( UDWORD player, BOOL bOnScreen) { DROID *psDroid; UDWORD damage; UDWORD count; selDroidDeselect(player); for(psDroid = apsDroidLists[player], count = 0; psDroid; psDroid = psDroid->psNext) { /* Get present percent of damage level */ damage = PERCENT(psDroid->body,psDroid->originalBody); /* Less than threshold? */ if(damage<REPAIRLEV_LOW) { /* Is on screen relevant? */ if(bOnScreen ? droidOnScreen(psDroid,0) : true) { //we don't want to get the Transporter if(psDroid->droidType != DROID_TRANSPORTER) { // psDroid->selected = true; SelectDroid(psDroid); count ++; } } } } return(count); }
bool intDisplayMultiJoiningStatus(UBYTE joinCount) { UDWORD x,y,w,h; char sTmp[6]; w = RET_FORMWIDTH; h = RET_FORMHEIGHT; x = RET_X; y = RET_Y; // cameraToHome(selectedPlayer); // home the camera to the player. RenderWindowFrame(FRAME_NORMAL, x, y ,w, h); // draw a wee blu box. // display how far done.. iV_DrawText(_("Players Still Joining"), x+(w/2)-(iV_GetTextWidth(_("Players Still Joining"))/2), y+(h/2)-8 ); if (!NetPlay.playercount) { return true; } sprintf(sTmp,"%d%%", PERCENT((NetPlay.playercount-joinCount),NetPlay.playercount) ); iV_DrawText(sTmp ,x + (w / 2) - 10, y + (h / 2) + 10); return true; }
_export bool module_finit() { unregister_packet_handler(D2GS_RECEIVED, 0x9c, d2gs_item_action); unregister_packet_handler(D2GS_RECEIVED, 0x15, d2gs_char_location_update); unregister_packet_handler(D2GS_RECEIVED, 0x95, d2gs_char_location_update); unregister_packet_handler(D2GS_SENT, 0x0c, d2gs_char_location_update); unregister_packet_handler(D2GS_RECEIVED, 0x19, d2gs_gold_update); unregister_packet_handler(D2GS_RECEIVED, 0x1d, d2gs_gold_update); unregister_packet_handler(D2GS_RECEIVED, 0x1e, d2gs_gold_update); unregister_packet_handler(D2GS_RECEIVED, 0x1f, d2gs_gold_update); //unregister_packet_handler(D2GS_RECEIVED, 0x20, d2gs_gold_update); //unregister_packet_handler(INTERNAL, 0x9c, internal_trigger_pickit); list_clear(&items); list_clear(&valuable); list_clear(&nolog); pthread_mutex_destroy(&items_m); ui_add_statistics_plugin("pickit", "attempts to pick items: %i\n", n_attempts); ui_add_statistics_plugin("pickit", "picked items: %i (%i%%)\n", n_picked, PERCENT(n_attempts, n_picked)); return TRUE; }
bool intDisplayMultiJoiningStatus(UBYTE joinCount) { UDWORD x,y,w,h; char sTmp[6]; w = RET_FORMWIDTH; h = RET_FORMHEIGHT; x = RET_X; y = RET_Y; // cameraToHome(selectedPlayer); // home the camera to the player. RenderWindowFrame(FRAME_NORMAL, x, y ,w, h); // draw a wee blu box. // display how far done.. iV_SetFont(font_regular); iV_DrawText(_("Players Still Joining"), x+(w/2)-(iV_GetTextWidth(_("Players Still Joining"))/2), y+(h/2)-8 ); unsigned playerCount = 0; // Calculate what NetPlay.playercount should be, which is apparently only non-zero for the host. for (unsigned player = 0; player < game.maxPlayers; ++player) { if (isHumanPlayer(player)) { ++playerCount; } } if (!playerCount) { return true; } iV_SetFont(font_large); sprintf(sTmp, "%d%%", PERCENT(playerCount - joinCount, playerCount)); iV_DrawText(sTmp ,x + (w / 2) - 10, y + (h / 2) + 10); iV_SetFont(font_small); int yStep = iV_GetTextLineSize(); int yPos = RET_Y - yStep*game.maxPlayers; static const std::string statusStrings[3] = {"☐ ", "☑ ", "☒ "}; for (unsigned player = 0; player < game.maxPlayers; ++player) { int status = -1; if (isHumanPlayer(player)) { status = ingame.JoiningInProgress[player]? 0 : 1; // Human player, still joining or joined. } else if (NetPlay.players[player].ai >= 0) { status = 2; // AI player (automatically joined). } if (status >= 0) { iV_DrawText((statusStrings[status] + getPlayerName(player)).c_str(), x + 5, yPos + yStep*NetPlay.players[player].position); } } return true; }
KeyFileInfo KeyFile::getInfo() { KeyFileHeader header; readHead(header,false); KeyPage page(header.m_keydef.getSize()); KeyFileInfo result; result.m_header = header; result.m_size = getSize(); result.m_pageInfo = m_pageInfo; if(header.m_root == DB_NULLADDR) { result.m_rootPageAddress = 0; result.m_rootPageItemCount = 0; result.m_treeHeight = 0; } else { result.m_rootPageAddress = getPageOffset(header.m_root); KeyPage page(m_keydef.getSize()); readPage(header.m_root,page); result.m_rootPageItemCount = page.getItemCount(); result.m_treeHeight = 1; for(KeyPageAddr addr = page.getChild(0); addr; addr = page.getChild(0)) { readPage(addr,page); result.m_treeHeight++; } } result.m_rootPageIndex = header.m_root; result.m_dataPageCount = (UINT)((result.m_size - sizeof(header)) / m_pageInfo.m_pageSize - header.m_freeListSize); UINT nonLeafPageCount = 0; UINT leafPageCount = 0; CompactIntArray &pageCountPerLevel = result.m_pageCountPerLevel; if(result.m_treeHeight == 0) { // file is empty pageCountPerLevel.add(0); } else { for(UINT l = 0; l < result.m_treeHeight; l++) { pageCountPerLevel.add(0); } pageCountPerLevel.first() = 1; KeyPageCounter pageCounter(pageCountPerLevel); pageScan(result.m_header.m_root, 0, pageCounter, max(0, result.m_treeHeight-3)); if(result.m_treeHeight >= 3) { for(size_t i = 0; i < pageCountPerLevel.size()-1; i++) { nonLeafPageCount += pageCountPerLevel[i]; } leafPageCount = pageCountPerLevel.last() = result.m_dataPageCount - nonLeafPageCount; } } const ULONG totalPageCount = result.m_dataPageCount + header.m_freeListSize; if(totalPageCount == 0) { result.m_utilizationRate = 100; } else { const INT64 maxKeys = (INT64)nonLeafPageCount * m_pageInfo.m_maxItemCount + (INT64)leafPageCount * m_pageInfo.m_maxKeyCount; result.m_utilizationRate = PERCENT(header.m_keyCount, maxKeys); } return result; }
void processLight(LIGHT *psLight) { SDWORD tileX,tileY; SDWORD startX,endX; SDWORD startY,endY; SDWORD rangeSkip; SDWORD i,j; SDWORD distToCorner; UDWORD percent; /* Firstly - there's no point processing lights that are off the grid */ if(clipXY(psLight->position.x,psLight->position.z) == false) { return; } tileX = psLight->position.x/TILE_UNITS; tileY = psLight->position.z/TILE_UNITS; rangeSkip = sqrtf(psLight->range * psLight->range * 2) / TILE_UNITS + 1; /* Rough guess? */ startX = tileX - rangeSkip; endX = tileX + rangeSkip; startY = tileY - rangeSkip; endY = tileY + rangeSkip; /* Clip to grid limits */ startX = MAX(startX, 0); endX = MAX(endX, 0); endX = MIN(endX, mapWidth - 1); startX = MIN(startX, endX); startY = MAX(startY, 0); endY = MAX(endY, 0); endY = MIN(endY, mapHeight - 1); startY = MIN(startY, endY); for(i=startX;i<=endX; i++) { for(j=startY; j<=endY; j++) { distToCorner = calcDistToTile(i,j,&psLight->position); /* If we're inside the range of the light */ if (distToCorner<(SDWORD)psLight->range) { /* Find how close we are to it */ percent = 100 - PERCENT(distToCorner,psLight->range); colourTile(i, j, psLight->colour, 2 * percent); } } } }
_export bool module_finit() { unregister_packet_handler(MCP_RECEIVED, 0x07, mcp_charlogon_handler); unregister_packet_handler(MCP_RECEIVED, 0x03, mcp_creategame_handler); unregister_packet_handler(MCP_RECEIVED, 0x04, mcp_joingame_handler); unregister_packet_handler(INTERNAL, D2GS_ENGINE_MESSAGE, on_d2gs_shutdown); unregister_packet_handler(INTERNAL, MCP_ENGINE_MESSAGE, on_mcp_cleanup); unregister_packet_handler(MCP_RECEIVED, 0x05, mcp_gamelist_handler); struct iterator it = list_iterator(&setting_cleaners); setting_cleanup_t *sc; while ((sc = iterator_next(&it))) { sc->cleanup(sc->set); } list_clear(&setting_cleaners); if (keyset) { free(keyset); keyset = NULL; n_keyset = 0; i_keyset = 0; rotated = FALSE; } pthread_cond_destroy(&game_created_cond_v); pthread_cond_destroy(&game_joined_cond_v); pthread_cond_destroy(&mcp_char_logon_cond_v); pthread_cond_destroy(&d2gs_engine_shutdown_cond_v); pthread_mutex_destroy(&game_created_mutex); pthread_mutex_destroy(&game_joined_mutex); pthread_mutex_destroy(&mcp_char_logon_mutex); pthread_mutex_destroy(&d2gs_engine_shutdown_mutex); pthread_mutex_destroy(&mcp_cleanup_m); pthread_cond_destroy(&mcp_cleanup_cv); pthread_mutex_destroy(&pub_m); pthread_cond_destroy(&pub_cv); list_clear(&public_games); ui_add_statistics_plugin("mcp game", "games created: %i\n", n_created); if (module_setting("JoinPublicGames")->b_var) ui_add_statistics_plugin("mcp game", "public games joined: %i\n", n_joined); ui_add_statistics_plugin("mcp game", "failed to join: %i (%i%%)\n", ftj, PERCENT(n_created, ftj)); return TRUE; }
// recv lassat info on the receiving end. bool recvLasSat(NETQUEUE queue) { BASE_OBJECT *psObj; UBYTE player, targetplayer; STRUCTURE *psStruct; uint32_t id, targetid; NETbeginDecode(queue, GAME_LASSAT); NETuint8_t(&player); NETuint32_t(&id); NETuint32_t(&targetid); NETuint8_t(&targetplayer); NETend(); psStruct = IdToStruct(id, player); psObj = IdToPointer(targetid, targetplayer); if (psStruct && !canGiveOrdersFor(queue.index, psStruct->player)) { syncDebug("Wrong player."); return false; } if (psStruct && psObj && psStruct->pStructureType->psWeapStat[0]->weaponSubClass == WSC_LAS_SAT) { // Lassats have just one weapon unsigned firePause = weaponFirePause(&asWeaponStats[psStruct->asWeaps[0].nStat], player); unsigned damLevel = PERCENT(psStruct->body, structureBody(psStruct)); if (damLevel < HEAVY_DAMAGE_LEVEL) { firePause += firePause; } if (isHumanPlayer(player) && gameTime - psStruct->asWeaps[0].lastFired <= firePause) { /* Too soon to fire again */ return true ^ false; // Return value meaningless and ignored. } // Give enemy no quarter, unleash the lasat proj_SendProjectile(&psStruct->asWeaps[0], NULL, player, psObj->pos, psObj, true, 0); psStruct->asWeaps[0].lastFired = gameTime; psStruct->asWeaps[0].ammo = 1; // abducting this field for keeping track of triggers // Play 5 second countdown message audio_QueueTrackPos(ID_SOUND_LAS_SAT_COUNTDOWN, psObj->pos.x, psObj->pos.y, psObj->pos.z); } return true; }
bool PCMAudio_SetStreamVolume( Sfx::sVolume *p_volume, int whichStream ) { if( gStreamInfo[whichStream].HasFileStream()) { // Adjust volumes for overall sound volume. Spt::SingletonPtr< Sfx::CSfxManager > sfx_manager; switch( p_volume->GetVolumeType()) { case Sfx::VOLUME_TYPE_5_CHANNEL_DOLBY5_1: { float v0 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 )); float v1 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 1 )); float v2 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 2 )); float v3 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 3 )); float v4 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 4 )); gStreamInfo[whichStream].volume = ( v0 + v1 + v2 + v3 + v4 ) * ( 1.0f / 5.0f ); gStreamInfo[whichStream].SetVolume( v0, v1, v2, v3, v4 ); break; } case Sfx::VOLUME_TYPE_2_CHANNEL_DOLBYII: { float v0 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 )); float v1 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 1 )); gStreamInfo[whichStream].volume = v0; gStreamInfo[whichStream].SetVolume( v0, v1 ); break; } case Sfx::VOLUME_TYPE_BASIC_2_CHANNEL: { float v0 = PERCENT( sfx_manager->GetMainVolume(), p_volume->GetChannelVolume( 0 )); gStreamInfo[whichStream].volume = v0; gStreamInfo[whichStream].SetVolume( v0 ); break; } default: { Dbg_Assert( 0 ); break; } } } return true; }
float CTerrainManager::sGetPitchPercent( STerrainSoundInfo *pInfo, float pitchPercent, bool clipToMaxPitch ) { Dbg_MsgAssert(pInfo, ("pInfo set to NULL.")); if ( !( ( pInfo->m_minPitch == 0.0f ) && ( pInfo->m_maxPitch == 100.0f ) ) ) { pitchPercent = ( pInfo->m_minPitch + PERCENT( ( pInfo->m_maxPitch - pInfo->m_minPitch ), pitchPercent ) ); } if ( clipToMaxPitch ) { if ( pitchPercent > pInfo->m_maxPitch ) pitchPercent = pInfo->m_maxPitch; } return ( pitchPercent ); }
// set the volume according to the range specified by the designers... float CTerrainManager::sGetVolPercent( STerrainSoundInfo *pInfo, float volPercent, bool clipToMaxVol ) { Dbg_MsgAssert(pInfo, ("pInfo set to NULL.")); if ( !( ( pInfo->m_minVol == 0.0f ) && ( pInfo->m_maxVol == 100.0f ) ) ) { volPercent = ( pInfo->m_minVol + PERCENT( ( pInfo->m_maxVol - pInfo->m_minVol ), volPercent ) ); } if ( clipToMaxVol ) { if ( volPercent > pInfo->m_maxVol ) volPercent = pInfo->m_maxVol; } return ( volPercent ); }
/* test on random values (but relatively small) */ static int test_2 (void) { guint i; guint n_success = 0; for (i = 0; i < 100000; i++) { if (test_float (g_random_int_range (-100000, 100000), g_random_int_range (0, 999999999))) { n_success ++; } } g_debug ("%d/%d tests suceeded (%.2f%%)", n_success, i, PERCENT (i, n_success)); return n_success == i ? 0 : 1; }
static profile_params_set_t COMPANY_PROFILE_PARAMS = { .shaper_params = { .commit_bps = 50 * MBPS, .commit_burst = 1000000, .peak_bps = 0, .peak_burst = 0, .dual_rate = FALSE, .shaper_len_adjust = 20 }, .threshold_params = { .max_pkts = 100000, .enable_max_pkts = TRUE, .max_bytes = 10000000, .enable_max_bytes = TRUE }, .wred_params = { [ODP_PACKET_GREEN ... ODP_PACKET_YELLOW] = { .min_threshold = PERCENT(70), .med_threshold = PERCENT(90), .med_drop_prob = PERCENT(80), .max_drop_prob = PERCENT(100), .enable_wred = TRUE, .use_byte_fullness = FALSE, }, [ODP_PACKET_RED] = { .min_threshold = PERCENT(40), .med_threshold = PERCENT(70), .med_drop_prob = PERCENT(70), .max_drop_prob = PERCENT(100), .enable_wred = TRUE, .use_byte_fullness = FALSE, },
static Word* subsub(Word *v, char *s, char *end) { int nmid; Word *head, *tail, *w, *h; Word *a, *b, *c, *d; Bufblock *buf; char *cp, *enda; a = extractpat(s, &cp, "=%&", end); b = c = d = 0; if(PERCENT(*cp)) b = extractpat(cp+1, &cp, "=", end); if(*cp == '=') c = extractpat(cp+1, &cp, "&%", end); if(PERCENT(*cp)) d = stow(cp+1); else if(*cp) d = stow(cp); head = tail = 0; buf = newbuf(); for(; v; v = v->next){ h = w = 0; if(submatch(v->s, a, b, &nmid, &enda)){ /* enda points to end of A match in source; * nmid = number of chars between end of A and start of B */ if(c){ h = w = wdup(c); while(w->next) w = w->next; } if(PERCENT(*cp) && nmid > 0){ if(w){ bufcpy(buf, w->s, strlen(w->s)); bufcpy(buf, enda, nmid); insert(buf, 0); free(w->s); w->s = strdup(buf->start); } else { bufcpy(buf, enda, nmid); insert(buf, 0); h = w = newword(buf->start); } buf->current = buf->start; } if(d && *d->s){ if(w){ bufcpy(buf, w->s, strlen(w->s)); bufcpy(buf, d->s, strlen(d->s)); insert(buf, 0); free(w->s); w->s = strdup(buf->start); w->next = wdup(d->next); while(w->next) w = w->next; buf->current = buf->start; } else h = w = wdup(d); } } if(w == 0) h = w = newword(v->s); if(head == 0) head = h; else tail->next = h; tail = w; } freebuf(buf); delword(a); delword(b); delword(c); delword(d); return head; }
void DumpArenaStats(JSGCArenaStats *stp, FILE *fp) { size_t sumArenas = 0, sumTotalArenas = 0, sumThings =0, sumMaxThings = 0; size_t sumThingSize = 0, sumTotalThingSize = 0, sumArenaCapacity = 0; size_t sumTotalArenaCapacity = 0, sumAlloc = 0, sumLocalAlloc = 0; for (int i = 0; i < (int) FINALIZE_LIMIT; i++) { JSGCArenaStats *st = &stp[i]; if (st->maxarenas == 0) continue; size_t thingSize = 0, thingsPerArena = 0; GetSizeAndThingsPerArena(i, thingSize, thingsPerArena); fprintf(fp, "%s arenas (thing size %lu, %lu things per arena):\n", GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena)); fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas)); fprintf(fp, " arenas after GC: %lu (%.1f%%)\n", UL(st->livearenas), PERCENT(st->livearenas, st->narenas)); fprintf(fp, " max arenas: %lu\n", UL(st->maxarenas)); fprintf(fp, " things: %lu\n", UL(st->nthings)); fprintf(fp, " GC cell utilization: %.1f%%\n", PERCENT(st->nthings, thingsPerArena * st->narenas)); fprintf(fp, " average cell utilization: %.1f%%\n", PERCENT(st->totalthings, thingsPerArena * st->totalarenas)); fprintf(fp, " max things: %lu\n", UL(st->maxthings)); fprintf(fp, " alloc attempts: %lu\n", UL(st->alloc)); fprintf(fp, " alloc without locks: %lu (%.1f%%)\n", UL(st->localalloc), PERCENT(st->localalloc, st->alloc)); sumArenas += st->narenas; sumTotalArenas += st->totalarenas; sumThings += st->nthings; sumMaxThings += st->maxthings; sumThingSize += thingSize * st->nthings; sumTotalThingSize += size_t(thingSize * st->totalthings); sumArenaCapacity += thingSize * thingsPerArena * st->narenas; sumTotalArenaCapacity += thingSize * thingsPerArena * st->totalarenas; sumAlloc += st->alloc; sumLocalAlloc += st->localalloc; putc('\n', fp); } fputs("Never used arenas:\n", fp); for (int i = 0; i < (int) FINALIZE_LIMIT; i++) { JSGCArenaStats *st = &stp[i]; if (st->maxarenas != 0) continue; fprintf(fp, "%s\n", GC_ARENA_NAMES[i]); } fprintf(fp, "\nTOTAL STATS:\n"); fprintf(fp, " total GC arenas: %lu\n", UL(sumArenas)); fprintf(fp, " total GC things: %lu\n", UL(sumThings)); fprintf(fp, " max total GC things: %lu\n", UL(sumMaxThings)); fprintf(fp, " GC cell utilization: %.1f%%\n", PERCENT(sumThingSize, sumArenaCapacity)); fprintf(fp, " average cell utilization: %.1f%%\n", PERCENT(sumTotalThingSize, sumTotalArenaCapacity)); fprintf(fp, " alloc attempts: %lu\n", UL(sumAlloc)); fprintf(fp, " alloc without locks: %lu (%.1f%%)\n", UL(sumLocalAlloc), PERCENT(sumLocalAlloc, sumAlloc)); }
/* Add the Droids back at home form */ bool intAddDroidsAvailForm(void) { UDWORD numButtons, i, butPerForm; SDWORD BufferID; DROID *psDroid; bool Animate = true; // Is the form already up? if (widgGetFromID(psWScreen, IDTRANS_DROIDS) != NULL) { intRemoveTransDroidsAvailNoAnim(); Animate = false; } if (intIsRefreshing()) { Animate = false; } /* Add the droids available form */ W_FORMINIT sFormInit; sFormInit.formID = 0; sFormInit.id = IDTRANS_DROIDS; sFormInit.style = WFORM_PLAIN; sFormInit.width = TRANSDROID_WIDTH; sFormInit.height = TRANSDROID_HEIGHT; sFormInit.x = (SWORD)TRANSDROID_X; sFormInit.y = (SWORD)TRANSDROID_Y; // If the window was closed then do open animation. if (Animate) { sFormInit.pDisplay = intOpenPlainForm; sFormInit.disableChildren = true; } else { // otherwise just recreate it. sFormInit.pDisplay = intDisplayPlainForm; } if (!widgAddForm(psWScreen, &sFormInit)) { return false; } /* Add the close button */ W_BUTINIT sButInit; sButInit.formID = IDTRANS_DROIDS; sButInit.id = IDTRANS_DROIDCLOSE; sButInit.x = TRANSDROID_WIDTH - CLOSE_WIDTH; sButInit.y = 0; sButInit.width = CLOSE_WIDTH; sButInit.height = CLOSE_HEIGHT; sButInit.pTip = _("Close"); sButInit.pDisplay = intDisplayImageHilight; sButInit.UserData = PACKDWORD_TRI(0, IMAGE_CLOSEHILIGHT , IMAGE_CLOSE); if (!widgAddButton(psWScreen, &sButInit)) { return false; } //now add the tabbed droids available form sFormInit = W_FORMINIT(); sFormInit.formID = IDTRANS_DROIDS; sFormInit.id = IDTRANS_DROIDTAB; sFormInit.style = WFORM_TABBED; sFormInit.width = TRANSDROID_TABWIDTH; sFormInit.height = TRANSDROID_TABHEIGHT; sFormInit.x = TRANSDROID_TABX; sFormInit.y = TRANSDROID_TABY; sFormInit.majorPos = WFORM_TABTOP; sFormInit.minorPos = WFORM_TABNONE; sFormInit.majorSize = (OBJ_TABWIDTH / 2); sFormInit.majorOffset = OBJ_TABOFFSET; sFormInit.tabVertOffset = (OBJ_TABHEIGHT / 2); sFormInit.tabMajorThickness = OBJ_TABHEIGHT; sFormInit.tabMajorGap = OBJ_TABOFFSET; //calc num buttons numButtons = 0; //look through the list of droids that were built before the mission for (psDroid = mission.apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext) { //ignore any Transporters! if (psDroid->droidType != DROID_TRANSPORTER && psDroid->droidType != DROID_SUPERTRANSPORTER) { numButtons++; } //quit when reached max can cope with if (numButtons == MAX_DROIDS) { break; } } butPerForm = ((TRANSDROID_TABWIDTH - OBJ_GAP) / (OBJ_BUTWIDTH + OBJ_GAP)) * ((TRANSDROID_TABHEIGHT - OBJ_GAP) / (OBJ_BUTHEIGHT + OBJ_GAP)); sFormInit.numMajor = numForms(numButtons, butPerForm); if (sFormInit.numMajor > MAX_TAB_SMALL_SHOWN) { // we DO use smallTab icons here, so be safe and only display max # of // small sized tab icons. No scrolltabs here. sFormInit.numMajor = MAX_TAB_SMALL_SHOWN; } //set minor tabs to 1 for (i = 0; i < sFormInit.numMajor; i++) { sFormInit.aNumMinors[i] = 1; } sFormInit.pUserData = &SmallTab; sFormInit.pTabDisplay = intDisplayTab; if (!widgAddForm(psWScreen, &sFormInit)) { return false; } /* Add the droids available buttons */ W_FORMINIT sBFormInit; sBFormInit.formID = IDTRANS_DROIDTAB; sBFormInit.id = IDTRANS_DROIDSTART; sBFormInit.majorID = 0; sBFormInit.minorID = 0; sBFormInit.style = WFORM_CLICKABLE; sBFormInit.x = OBJ_STARTX; sBFormInit.y = AVAIL_STARTY; sBFormInit.width = OBJ_BUTWIDTH; sBFormInit.height = OBJ_BUTHEIGHT; ClearSystem0Buffers(); /* Add the state of repair bar for each droid*/ W_BARINIT sBarInit; sBarInit.id = IDTRANS_REPAIRBARSTART; sBarInit.x = STAT_TIMEBARX; sBarInit.y = STAT_TIMEBARY; sBarInit.width = STAT_PROGBARWIDTH; sBarInit.height = STAT_PROGBARHEIGHT; sBarInit.size = 50; sBarInit.sCol = WZCOL_ACTION_PROGRESS_BAR_MAJOR; sBarInit.sMinorCol = WZCOL_ACTION_PROGRESS_BAR_MINOR; //add droids built before the mission for (psDroid = mission.apsDroidLists[selectedPlayer]; psDroid != NULL; psDroid = psDroid->psNext) { //stop adding the buttons once MAX_DROIDS has been reached if (sBFormInit.id == (IDTRANS_DROIDSTART + MAX_DROIDS)) { break; } //don't add Transporter Droids! if ((psDroid->droidType != DROID_TRANSPORTER && psDroid->droidType != DROID_SUPERTRANSPORTER)) { /* Set the tip and add the button */ sBFormInit.pTip = droidGetName(psDroid); BufferID = GetSystem0Buffer(); ASSERT(BufferID >= 0, "Unable to acquire stat buffer."); RENDERBUTTON_INUSE(&System0Buffers[BufferID]); System0Buffers[BufferID].Data = (void *)psDroid; sBFormInit.pUserData = &System0Buffers[BufferID]; sBFormInit.pDisplay = intDisplayTransportButton; if (!widgAddForm(psWScreen, &sBFormInit)) { return false; } //add bar to indicate stare of repair sBarInit.size = (UWORD) PERCENT(psDroid->body, psDroid->originalBody); if (sBarInit.size > 100) { sBarInit.size = 100; } sBarInit.formID = sBFormInit.id; //sBarInit.iRange = TBAR_MAX_REPAIR; if (!widgAddBarGraph(psWScreen, &sBarInit)) { return false; } /* Update the init struct for the next button */ sBFormInit.id += 1; ASSERT(sBFormInit.id < IDTRANS_DROIDEND, "Too many Droids Built buttons"); sBFormInit.x += OBJ_BUTWIDTH + OBJ_GAP; if (sBFormInit.x + OBJ_BUTWIDTH + OBJ_GAP > TRANSDROID_TABWIDTH) { sBFormInit.x = OBJ_STARTX; sBFormInit.y += OBJ_BUTHEIGHT + OBJ_GAP; } if (sBFormInit.y + OBJ_BUTHEIGHT + OBJ_GAP > TRANSDROID_TABHEIGHT) { sBFormInit.y = AVAIL_STARTY; sBFormInit.majorID += 1; } //and bar sBarInit.id += 1; } } //reset which tab we were on if (objMajor > (UWORD)(sFormInit.numMajor - 1)) { //set to last if have lost a tab widgSetTabs(psWScreen, IDTRANS_DROIDTAB, (UWORD)(sFormInit.numMajor - 1), objMinor); } else { //set to same tab we were on previously widgSetTabs(psWScreen, IDTRANS_DROIDTAB, objMajor, objMinor); } return true; }
// ----------------------------------------------------------------------------------- void fillUpStats( void ) { UDWORD i; UDWORD maxi,num; float scaleFactor; UDWORD length; UDWORD numUnits; DROID *psDroid; /* Do rankings first cos they're easier */ for(i=0,maxi=0; i<DROID_LEVELS; i++) { num = getNumDroidsForLevel(i); if(num>maxi) { maxi = num; } } /* Make sure we got something */ if(maxi == 0) { scaleFactor = 0.f; } else { scaleFactor = (float)RANK_BAR_WIDTH / maxi; } /* Scale for percent */ for(i=0; i<DROID_LEVELS; i++) { length = scaleFactor * getNumDroidsForLevel(i); infoBars[STAT_ROOKIE+i].percent = PERCENT(length,RANK_BAR_WIDTH); infoBars[STAT_ROOKIE+i].number = getNumDroidsForLevel(i); } /* Now do the other stuff... */ /* Units killed and lost... */ maxi = MAX(missionData.unitsLost, missionData.unitsKilled); if (maxi == 0) { scaleFactor = 0.f; } else { scaleFactor = (float)STAT_BAR_WIDTH / maxi; } length = scaleFactor * missionData.unitsLost; infoBars[STAT_UNIT_LOST].percent = PERCENT(length,STAT_BAR_WIDTH); length = scaleFactor * missionData.unitsKilled; infoBars[STAT_UNIT_KILLED].percent = PERCENT(length,STAT_BAR_WIDTH); /* Now do the structure losses */ maxi = MAX(missionData.strLost, missionData.strKilled); if (maxi == 0) { scaleFactor = 0.f; } else { scaleFactor = (float)STAT_BAR_WIDTH / maxi; } length = scaleFactor * missionData.strLost; infoBars[STAT_STR_LOST].percent = PERCENT(length,STAT_BAR_WIDTH); length = scaleFactor * missionData.strKilled; infoBars[STAT_STR_BLOWN_UP].percent = PERCENT(length,STAT_BAR_WIDTH); /* Finally the force information - need amount of droids as well*/ for(psDroid = apsDroidLists[selectedPlayer], numUnits = 0; psDroid; psDroid = psDroid->psNext, numUnits++) {} for(psDroid = mission.apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext, numUnits++) {} maxi = MAX(missionData.unitsBuilt, missionData.strBuilt); maxi = MAX(maxi, numUnits); if (maxi == 0) { scaleFactor = 0.f; } else { scaleFactor = (float)STAT_BAR_WIDTH / maxi; } length = scaleFactor * missionData.unitsBuilt; infoBars[STAT_UNITS_BUILT].percent = PERCENT(length,STAT_BAR_WIDTH); length = scaleFactor * numUnits; infoBars[STAT_UNITS_NOW].percent = PERCENT(length,STAT_BAR_WIDTH); length = scaleFactor * missionData.strBuilt; infoBars[STAT_STR_BUILT].percent = PERCENT(length,STAT_BAR_WIDTH); /* Finally the numbers themselves */ infoBars[STAT_UNIT_LOST].number = missionData.unitsLost; infoBars[STAT_UNIT_KILLED].number = missionData.unitsKilled; infoBars[STAT_STR_LOST].number = missionData.strLost; infoBars[STAT_STR_BLOWN_UP].number = missionData.strKilled; infoBars[STAT_UNITS_BUILT].number = missionData.unitsBuilt; infoBars[STAT_UNITS_NOW].number = numUnits; infoBars[STAT_STR_BUILT].number = missionData.strBuilt; }
/* Add the Droids back at home form */ bool intAddDroidsAvailForm(void) { // Is the form already up? bool Animate = true; if (widgGetFromID(psWScreen, IDTRANS_DROIDS) != NULL) { intRemoveTransDroidsAvailNoAnim(); Animate = false; } if (intIsRefreshing()) { Animate = false; } WIDGET *parent = psWScreen->psForm; /* Add the droids available form */ IntFormAnimated *transDroids = new IntFormAnimated(parent, Animate); // Do not animate the opening, if the window was already open. transDroids->id = IDTRANS_DROIDS; transDroids->setGeometry(TRANSDROID_X, TRANSDROID_Y, TRANSDROID_WIDTH, TRANSDROID_HEIGHT); /* Add the close button */ W_BUTINIT sButInit; sButInit.formID = IDTRANS_DROIDS; sButInit.id = IDTRANS_DROIDCLOSE; sButInit.x = TRANSDROID_WIDTH - CLOSE_WIDTH; sButInit.y = 0; sButInit.width = CLOSE_WIDTH; sButInit.height = CLOSE_HEIGHT; sButInit.pTip = _("Close"); sButInit.pDisplay = intDisplayImageHilight; sButInit.UserData = PACKDWORD_TRI(0, IMAGE_CLOSEHILIGHT , IMAGE_CLOSE); if (!widgAddButton(psWScreen, &sButInit)) { return false; } //now add the tabbed droids available form IntListTabWidget *droidList = new IntListTabWidget(transDroids); droidList->id = IDTRANS_DROIDTAB; droidList->setChildSize(OBJ_BUTWIDTH, OBJ_BUTHEIGHT); droidList->setChildSpacing(OBJ_GAP, OBJ_GAP); int droidListWidth = OBJ_BUTWIDTH*2 + OBJ_GAP; droidList->setGeometry((TRANSDROID_WIDTH - droidListWidth)/2, AVAIL_STARTY + 15, droidListWidth, TRANSDROID_HEIGHT - (AVAIL_STARTY + 15)); /* Add the droids available buttons */ int nextButtonId = IDTRANS_DROIDSTART; /* Add the state of repair bar for each droid*/ W_BARINIT sBarInit; sBarInit.id = IDTRANS_REPAIRBARSTART; sBarInit.x = STAT_TIMEBARX; sBarInit.y = STAT_TIMEBARY; sBarInit.width = STAT_PROGBARWIDTH; sBarInit.height = STAT_PROGBARHEIGHT; sBarInit.size = 50; sBarInit.sCol = WZCOL_ACTION_PROGRESS_BAR_MAJOR; sBarInit.sMinorCol = WZCOL_ACTION_PROGRESS_BAR_MINOR; //add droids built before the mission for (DROID *psDroid = mission.apsDroidLists[selectedPlayer]; psDroid != nullptr; psDroid = psDroid->psNext) { //stop adding the buttons once IDTRANS_DROIDEND has been reached if (nextButtonId == IDTRANS_DROIDEND) { break; } //don't add Transporter Droids! if ((psDroid->droidType != DROID_TRANSPORTER && psDroid->droidType != DROID_SUPERTRANSPORTER)) { /* Set the tip and add the button */ IntTransportButton *button = new IntTransportButton(droidList); button->id = nextButtonId; button->setTip(droidGetName(psDroid)); button->setObject(psDroid); droidList->addWidgetToLayout(button); //add bar to indicate stare of repair sBarInit.size = (UWORD) PERCENT(psDroid->body, psDroid->originalBody); if (sBarInit.size > 100) { sBarInit.size = 100; } sBarInit.formID = nextButtonId; //sBarInit.iRange = TBAR_MAX_REPAIR; if (!widgAddBarGraph(psWScreen, &sBarInit)) { return false; } /* Update the init struct for the next button */ ++nextButtonId; ASSERT(nextButtonId < IDTRANS_DROIDEND, "Too many Droids Built buttons"); //and bar sBarInit.id += 1; } } //reset which tab we were on droidList->setCurrentPage(objMajor); return true; }
/** * Calculate and obtain the core variables. Each raw ADC value is converted to a * usable measurement via a variety of methods. They are then stored in a struct * and used as input to the next phase. */ void generateCoreVars(){ // Battery Reference Voltage unsigned short localBRV; if(!(fixedConfigs2.sensorSources.BRV)){ localBRV = (((unsigned long)ADCBuffers->BRV * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum; }else if(fixedConfigs2.sensorSources.BRV == SOURCE_PRESET){ localBRV = fixedConfigs2.sensorPresets.presetBRV; }else if(fixedConfigs2.sensorSources.BRV == SOURCE_LINEAR){ localBRV = (ADCBuffers->BRV * 14) + VOLTS(7.2); // 0 ADC = 7.2V, 1023 ADC = 21.522C }else{ // Default to normal alternator charging voltage 14.4V localBRV = VOLTS(14.4); } // Coolant/Head Temperature unsigned short localCHT; if(!(fixedConfigs2.sensorSources.CHT)){ localCHT = CHTTransferTable[ADCBuffers->CHT]; }else if(fixedConfigs2.sensorSources.CHT == SOURCE_PRESET){ localCHT = fixedConfigs2.sensorPresets.presetCHT; }else if(fixedConfigs2.sensorSources.CHT == SOURCE_LINEAR){ localCHT = (ADCBuffers->CHT * 10) + DEGREES_C(0); // 0 ADC = 0C, 1023 ADC = 102.3C }else{ // Default to slightly cold and therefore rich: 65C localCHT = DEGREES_C(65); } // Inlet Air Temperature unsigned short localIAT; if(!(fixedConfigs2.sensorSources.IAT)){ localIAT = IATTransferTable[ADCBuffers->IAT]; }else if(fixedConfigs2.sensorSources.IAT == SOURCE_PRESET){ localIAT = fixedConfigs2.sensorPresets.presetIAT; }else if(fixedConfigs2.sensorSources.IAT == SOURCE_LINEAR){ localIAT = (ADCBuffers->IAT * 10) + DEGREES_C(0); // 0 ADC = 0C, 1023 ADC = 102.3C }else{ // Default to room temperature localIAT = DEGREES_C(20); } // Throttle Position Sensor /* Bound the TPS ADC reading and shift it to start at zero */ unsigned short unboundedTPSADC = ADCBuffers->TPS; unsigned short boundedTPSADC; if(fixedConfigs2.sensorRanges.TPSMaximumADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMaximumADC){ boundedTPSADC = TPSADCRange; }else if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ boundedTPSADC = unboundedTPSADC - fixedConfigs2.sensorRanges.TPSMinimumADC; } else{ boundedTPSADC = 0; } }else{ // Reverse slope! if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ boundedTPSADC = 0; }else if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMaximumADC){ boundedTPSADC = fixedConfigs2.sensorRanges.TPSMinimumADC - unboundedTPSADC; }else{ boundedTPSADC = TPSADCRange; } } /* Get TPS from ADC no need to add TPS min as we know it is zero by definition */ unsigned short localTPS = ((unsigned long)boundedTPSADC * PERCENT(100)) / TPSADCRange; // TODO fail safe mode, only if on the ADC rails AND configured to do so // Default to a low value that will get you home if you are in Alpha-N mode /* Get RPM by locking out ISRs for a second and grabbing the Tooth logging data */ //atomic start // copy rpm data //atomic end // Calculate RPM and delta RPM and delta delta RPM from data recorded if(*ticksPerDegree != 0){ CoreVars->RPM = (unsigned short)(degreeTicksPerMinute / *ticksPerDegree); }else{ CoreVars->RPM = 0; } CoreVars->DRPM = *ticksPerDegree; // unsigned short localDRPM = 0; // unsigned short localDDRPM = 0; // TODO This might get done somewhere else, separation of concerns, etc /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Average the variables as per the configuration &&&&&&&&&&&&&&&&&&&&&&&&&&*/ /* Strictly speaking only the primary variables need to be averaged. After that, the derived ones are */ /* already averaged in a way. However, there may be some advantage to some short term averaging on the */ /* derived ones also, so it is something to look into later. */ /// @todo TODO average the generated values here // newVal var word ' the value from the ADC // smoothed var word ' a nicely smoothed result // // if newval > smoothed then // smoothed = smoothed + (newval - smoothed)/alpha // else // smoothed = smoothed - (smoothed - newval)/alpha // endif // from : http://www.tigoe.net/pcomp/code/category/code/arduinowiring/41 // for now just copy them in. CoreVars->BRV = localBRV; CoreVars->CHT = localCHT; CoreVars->IAT = localIAT; CoreVars->TPS = localTPS; CoreVars->EGO = (((unsigned long)ADCBuffers->EGO * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum; CoreVars->MAP = (((unsigned long)ADCBuffers->MAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum; CoreVars->AAP = (((unsigned long)ADCBuffers->AAP * fixedConfigs2.sensorRanges.AAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.AAPMinimum; CoreVars->MAT = IATTransferTable[ADCBuffers->MAT]; // Not actually used, feed raw values for now TODO migrate these to a SpecialVars struct or similar not included in default datalog CoreVars->EGO2 = ADCBuffers->EGO2; CoreVars->IAP = ADCBuffers->IAP; CoreVars->MAF = MAFTransferTable[ADCBuffers->MAF]; // CoreVars->DRPM = localDRPM; // CoreVars->DDRPM = localDDRPM; // CoreVars->DTPS = localDTPS; }
static bool selDamaged(DROID *droid) { return PERCENT(droid->body, droid->originalBody) < REPAIRLEV_LOW && !selTransporter(droid); }
ECCPowerDownInProgress = 0x10000000u, ECCRebalanceRequired = 0x08000000u, ECCRebalanceTimerQueued = 0x04000000u, ECCPeriodicBalancingActive = 0x02000000u, }; const TUint K_CpuMask = 0x1fu; const TUint K_Keep = 0x20u; const TUint K_SameCpu = 0x40u; const TUint K_NewCpu = 0x80u; const TUint K_CpuSticky = 0x40u; const TUint K_CheckCpu = 0x100u; #define PERCENT(fsd, percent) (((fsd)*(percent)+50)/100) const TUint K_LB_HeavyThreshold = PERCENT(4095, 90); const TUint K_LB_GravelThreshold_RunAvg = PERCENT(4095, 1); const TUint K_LB_GravelThreshold_RunActAvg = PERCENT(4095, 50); const TInt K_LB_HeavyCapacityThreshold = PERCENT(4095, 1); const TInt K_LB_BalanceInterval = 107; const TInt K_LB_CpuLoadDiffThreshold = 128; //const TUint K_LB_HeavyStateThreshold = 128; const TUint K_LB_HeavyPriorityThreshold = 25; inline TBool IsHeavy(NSchedulable* a) { TUint x = 0xffu ^ a->iLbInfo.iLbHeavy; return (x&(x-1))==0; }
/** @brief Generate the core variables and average them. * * Each raw ADC value is converted to a usable measurement via a variety of * methods chosen at runtime by configured settings. Once in their native units * and therefore closer to maximal use of the available data range they are * all averaged. * * @todo TODO incorporate averaging code, right now its a straight copy. * @todo TODO change the way configuration is done and make sure the most common options are after the first if(). * @todo TODO add actual configuration options to the fixed config blocks for these items. * * @author Fred Cooke */ void generateCoreVars(){ /*&&&&&&&& Calculate and obtain the basic variables with which we will perform the calculations &&&&&&&&*/ /* Pre calculate things used in multiple places */ /* Bound the TPS ADC reading and shift it to start at zero */ unsigned short unboundedTPSADC = ADCBuffers->TPS; if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMaximumADC){ boundedTPSADC = TPSADCRange; }else if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ // force secondary config to be used... TODO remove this boundedTPSADC = unboundedTPSADC - fixedConfigs2.sensorRanges.TPSMinimumADC; }else{ boundedTPSADC = 0; } /* Get BRV from ADC using transfer variables (all installations need this) */ unsigned short localBRV; if(TRUE){ /* If BRV connected */ /// @todo TODO WARNING: HACK!!! Remove ASAP!!! IE, As Soon As Preston (get's a new cpu on the TA card!) #ifdef HOTEL localBRV = (((unsigned long)ADCBuffers->MAT * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum; #else localBRV = (((unsigned long)ADCBuffers->BRV * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum; #endif }else if(FALSE){ /* Configured to be fixed value */ /* Get the preferred BRV figure from configuration settings */ localBRV = fixedConfigs2.sensorPresets.presetBRV; }else{ /* Fail safe if config is broken */ /* Default to normal alternator charging voltage 14.4V */ localBRV = VOLTS(14.4); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(BRV_NOT_CONFIGURED_CODE); } unsigned short localCHT; /* Get CHT from ADC using the transfer table (all installations need this) */ if(TRUE){ /* If CHT connected */ localCHT = CHTTransferTable[ADCBuffers->CHT]; }else if(FALSE){ /* Configured to be read From ADC as dashpot */ /* Transfer the ADC reading to an engine temperature in a reasonable way */ localCHT = (ADCBuffers->CHT * 10) + DEGREES_C(0); /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */ }else if(FALSE){ /* Configured to be fixed value */ /* Get the preferred CHT figure from configuration settings */ localCHT = fixedConfigs2.sensorPresets.presetCHT; }else{ /* Fail safe if config is broken */ /* Default to normal running temperature of 85C/358K */ localCHT = DEGREES_C(85); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(CHT_NOT_CONFIGURED_CODE); } unsigned short localIAT; /* Get IAT from ADC using the transfer table (all installations need this) */ if(TRUE){ /* If IAT connected */ /* using false here causes iat to default to room temp, useful with heatsoaked OEM sensors like the Volvo's... */ localIAT = IATTransferTable[ADCBuffers->IAT]; }else if(FALSE){ /* Configured to be read From ADC as dashpot */ /* Transfer the ADC reading to an air temperature in a reasonable way */ localIAT = (ADCBuffers->IAT * 10) + 27315; /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */ }else if(FALSE){ /* Configured to be fixed value */ /* Get the preferred IAT figure from configuration settings */ localIAT = fixedConfigs2.sensorPresets.presetIAT; }else{ /* Fail safe if config is broken */ /* Default to room temperature (20C/293K) TODO poor choice, fix. */ localIAT = DEGREES_C(20); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(IAT_NOT_CONFIGURED_CODE); } unsigned short localMAT; /* Determine the MAT reading for future calculations */ if(TRUE){ /* If MAT sensor is connected */ /* Get MAT from ADC using same transfer table as IAT (too much space to waste on having two) */ localMAT = IATTransferTable[ADCBuffers->MAT]; }else if(FALSE){ /* Configured to be fixed value */ /* Get the preferred MAT figure from configuration settings */ localMAT = fixedConfigs2.sensorPresets.presetMAT; }else{ /* Fail safe if config is broken */ /* If not, default to same value as IAT */ localMAT = localIAT; /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(MAT_NOT_CONFIGURED_CODE); } unsigned short localMAP; unsigned short localIAP; /* Determine the MAP pressure to use for future calculations */ if(TRUE){ /* If MAP sensor is connected */ /* get MAP from ADC using transfer variables */ localMAP = (((unsigned long)ADCBuffers->MAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum; if(TRUE){ /* If Intercooler boost sensor connected */ /* Get IAP from ADC using the same transfer variables as they both need to read the same range */ localIAP = (((unsigned long)ADCBuffers->IAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum; } }else if(FALSE){ /* Configured for MAP to imitate TPS signal */ /* Get MAP from TPS via conversion */ localMAP = (((unsigned long)boundedTPSADC * TPSMAPRange) / TPSADCRange) + fixedConfigs2.sensorRanges.TPSClosedMAP; }else if(FALSE){ /* Configured for dash potentiometer on ADC */ /* Get MAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */ localMAP = ADCBuffers->MAP << 6; if(TRUE){ /* If Intercooler boost sensor enabled */ /* Get IAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */ localIAP = ADCBuffers->IAP << 6; } }else if(FALSE){ /* Configured for fixed MAP from config */ /* Get the preferred MAP figure from configuration settings */ localMAP = fixedConfigs2.sensorPresets.presetMAP; }else{ /* Fail safe if config is broken */ /* Default to zero to nulify all other calcs and effectively cut fuel */ localMAP = 0; /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(MAP_NOT_CONFIGURED_CODE); // or maybe queue it? } /* Determine MAF variable if required */ unsigned short localMAF = 0; // Default to zero as it is not required for anything except main PW calcs optionally if(TRUE){ localMAF = MAFTransferTable[ADCBuffers->MAF]; } unsigned short localAAP; /* Determine the Atmospheric pressure to use for future calculations */ if(TRUE){ /* Configured for second sensor to read AAP */ /* get AAP from ADC using separate vars to allow 115kPa sensor etc to be used */ localAAP = (((unsigned long)ADCBuffers->AAP * fixedConfigs2.sensorRanges.AAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.AAPMinimum; }else if(FALSE){ /* Configured for dash potentiometer on ADC */ /* Get AAP from ADC via conversion to internal kPa figure where 1023ADC = 102.3kPa */ localAAP = ADCBuffers->AAP * 10; }else if(FALSE){ /* Configured for fixed AAP from config */ /* Get the preferred AAP figure from configuration settings */ localAAP = fixedConfigs2.sensorPresets.presetAAP; }else{ /* Fail safe if config is broken */ /* Default to sea level */ localAAP = KPA(100); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(AAP_NOT_CONFIGURED_CODE); // or maybe queue it? } unsigned short localEGO; /* Get main Lambda reading */ if(TRUE){ /* If WBO2-1 is connected */ /* Get EGO from ADCs using transfer variables */ localEGO = (((unsigned long)ADCBuffers->EGO * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum; }else if(FALSE){ /* Configured for fixed EGO from config */ /* Get the preferred EGO figure from configuration settings */ localEGO = fixedConfigs2.sensorPresets.presetEGO; }else{ /* Default value if not connected incase other things are misconfigured */ /* Default to stoichiometric */ localEGO = LAMBDA(1.0); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(EGO_NOT_CONFIGURED_CODE); // or maybe queue it? } unsigned short localEGO2; /* Get second Lambda reading */ if(TRUE){ /* If WBO2-2 is connected */ /* Get EGO2 from ADCs using same transfer variables as EGO */ localEGO2 = (((unsigned long)ADCBuffers->EGO2 * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum; }else if(FALSE){ /* Configured for fixed EGO2 from config */ /* Get the preferred EGO2 figure from configuration settings */ localEGO2 = fixedConfigs2.sensorPresets.presetEGO2; }else{ /* Default value if not connected incase other things are misconfigured */ /* Default to stoichiometric */ localEGO2 = LAMBDA(1.0); /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(EGO2_NOT_CONFIGURED_CODE); // or maybe queue it? } unsigned short localTPS; /* Get TPS percentage */ if(TRUE){ /* If TPS is connected */ /* Get TPS from ADC no need to add TPS min as we know it is zero by definition */ localTPS = ((unsigned long)boundedTPSADC * PERCENT(100)) / TPSADCRange; }else if(FALSE){ /* Configured for TPS to imitate MAP signal */ /* Get TPS from MAP via conversion */ /* Box MAP signal down */ if(localTPS > fixedConfigs2.sensorRanges.TPSOpenMAP){ /* Greater than ~95kPa */ localTPS = PERCENT(100); }else if(localTPS < fixedConfigs2.sensorRanges.TPSClosedMAP){ /* Less than ~30kPa */ localTPS = 0; }else{ /* Scale MAP range to TPS range */ localTPS = localMAP - fixedConfigs2.sensorRanges.TPSClosedMAP; } // get TPS from MAP no need to add TPS min as we know it is zero by definition localTPS = ((unsigned long)localTPS * PERCENT(100)) / (fixedConfigs2.sensorRanges.TPSOpenMAP - fixedConfigs2.sensorRanges.TPSClosedMAP); }else if(FALSE){ /* Configured for dash potentiometer on ADC */ /* Get TPS from ADC as shown : 1023 ADC = 100%, 0 ADC = 0% */ localTPS = ((unsigned long)ADCBuffers->TPS * PERCENT(100)) / ADC_DIVISIONS; }else if(FALSE){ /* Configured for fixed TPS from config */ /* Get the preferred TPS figure from configuration settings */ localTPS = fixedConfigs2.sensorPresets.presetTPS; }else{ /* Fail safe if config is broken */ /* Default to 50% to not trigger any WOT or CT conditions */ localTPS = PERCENT(50); // TODO YAGNI? /* If anyone is listening, let them know something is wrong */ sendErrorIfClear(TPS_NOT_CONFIGURED_CODE); // or maybe queue it? } /* Get RPM by locking out ISRs for a second and grabbing the Tooth logging data */ //atomic start // copy rpm data //atomic end // Calculate RPM and delta RPM and delta delta RPM from data recorded if(*ticksPerDegree != 0){ CoreVars->RPM = (unsigned short)(degreeTicksPerMinute / *ticksPerDegree); }else{ CoreVars->RPM = 0; } CoreVars->DRPM = *ticksPerDegree; // unsigned short localDRPM = 0; // unsigned short localDDRPM = 0; /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Average the variables as per the configuration &&&&&&&&&&&&&&&&&&&&&&&&&&*/ /* Strictly speaking only the primary variables need to be averaged. After that, the derived ones are */ /* already averaged in a way. However, there may be some advantage to some short term averaging on the */ /* derived ones also, so it is something to look into later. */ /// @todo TODO average the generated values here // newVal var word ' the value from the ADC // smoothed var word ' a nicely smoothed result // // if newval > smoothed then // smoothed = smoothed + (newval - smoothed)/alpha // else // smoothed = smoothed - (smoothed - newval)/alpha // endif // from : http://www.tigoe.net/pcomp/code/category/code/arduinowiring/41 // for now just copy them in. CoreVars->IAT = localIAT; CoreVars->CHT = localCHT; CoreVars->TPS = localTPS; CoreVars->EGO = localEGO; CoreVars->BRV = localBRV; CoreVars->MAP = localMAP; CoreVars->AAP = localAAP; CoreVars->MAT = localMAT; CoreVars->EGO2 = localEGO2; CoreVars->IAP = localIAP; CoreVars->MAF = localMAF; // CoreVars->DRPM = localDRPM; // CoreVars->DDRPM = localDDRPM; // CoreVars->DTPS = localDTPS; // later... unsigned short i; for(i=0;i<sizeof(CoreVar);i++){ // TODO /* Perform averaging on all primary variables as per the configuration array */ // get old value(s) // process new and old to produce result based on config array value */ // assign result to old value holder } // TODO /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ }
/* Fire a weapon at something */ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, int weapon_slot) { WEAPON_STATS *psStats; UDWORD damLevel; UDWORD firePause; SDWORD longRange; DROID *psDroid = NULL; int compIndex; CHECK_OBJECT(psAttacker); CHECK_OBJECT(psTarget); ASSERT(psWeap != NULL, "Invalid weapon pointer"); /* Watermelon:dont shoot if the weapon_slot of a vtol is empty */ if (psAttacker->type == OBJ_DROID && isVtolDroid(((DROID *)psAttacker))) { if (((DROID *)psAttacker)->sMove.iAttackRuns[weapon_slot] >= getNumAttackRuns(((DROID *)psAttacker), weapon_slot)) { objTrace(psAttacker->id, "VTOL slot %d is empty", weapon_slot); return false; } } /* Get the stats for the weapon */ compIndex = psWeap->nStat; ASSERT_OR_RETURN( false , compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); psStats = asWeaponStats + compIndex; // check valid weapon/prop combination if (!validTarget(psAttacker, psTarget, weapon_slot)) { return false; } /*see if reload-able weapon and out of ammo*/ if (psStats->reloadTime && !psWeap->ammo) { if (gameTime - psWeap->lastFired < weaponReloadTime(psStats, psAttacker->player)) { return false; } //reset the ammo level psWeap->ammo = psStats->numRounds; } /* See when the weapon last fired to control it's rate of fire */ firePause = weaponFirePause(psStats, psAttacker->player); // increase the pause if heavily damaged switch (psAttacker->type) { case OBJ_DROID: psDroid = (DROID *)psAttacker; damLevel = PERCENT(psDroid->body, psDroid->originalBody); break; case OBJ_STRUCTURE: damLevel = PERCENT(((STRUCTURE *)psAttacker)->body, structureBody((STRUCTURE *)psAttacker)); break; default: damLevel = 100; break; } if (damLevel < HEAVY_DAMAGE_LEVEL) { firePause += firePause; } if (gameTime - psWeap->lastFired <= firePause) { /* Too soon to fire again */ return false; } // add a random delay to the fire // With logical updates, a good graphics gard no longer gives a better ROF. // TODO Should still replace this with something saner, such as a ±1% random deviation in reload time. int fireChance = gameTime - (psWeap->lastFired + firePause); if (gameRand(RANDOM_PAUSE) > fireChance) { return false; } if (psTarget->visible[psAttacker->player] != UBYTE_MAX) { // Can't see it - can't hit it objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target", psAttacker->id, psStats->pName, psTarget->id); return false; } /* Check we can see the target */ if (psAttacker->type == OBJ_DROID && !isVtolDroid((DROID *)psAttacker) && (proj_Direct(psStats) || actionInsideMinRange(psDroid, psTarget, psStats))) { if(!lineOfFire(psAttacker, psTarget, weapon_slot, true)) { // Can't see the target - can't hit it with direct fire objTrace(psAttacker->id, "combFire(%u[%s]->%u): Droid has no direct line of sight to target", psAttacker->id, ((DROID *)psAttacker)->aName, psTarget->id); return false; } } else if ((psAttacker->type == OBJ_STRUCTURE) && (((STRUCTURE *)psAttacker)->pStructureType->height == 1) && proj_Direct(psStats)) { // a bunker can't shoot through walls if (!lineOfFire(psAttacker, psTarget, weapon_slot, true)) { // Can't see the target - can't hit it with direct fire objTrace(psAttacker->id, "combFire(%u[%s]->%u): Structure has no direct line of sight to target", psAttacker->id, ((STRUCTURE *)psAttacker)->pStructureType->pName, psTarget->id); return false; } } else if ( proj_Direct(psStats) ) { // VTOL or tall building if (!lineOfFire(psAttacker, psTarget, weapon_slot, false)) { // Can't see the target - can't hit it with direct fire objTrace(psAttacker->id, "combFire(%u[%s]->%u): Tall object has no direct line of sight to target", psAttacker->id, psStats->pName, psTarget->id); return false; } } Vector3i deltaPos = psTarget->pos - psAttacker->pos; // if the turret doesn't turn, check if the attacker is in alignment with the target if (psAttacker->type == OBJ_DROID && !psStats->rotate) { uint16_t targetDir = iAtan2(removeZ(deltaPos)); int dirDiff = abs(angleDelta(targetDir - psAttacker->rot.direction)); if (dirDiff > FIXED_TURRET_DIR) { return false; } } /* Now see if the target is in range - also check not too near */ int dist = iHypot(removeZ(deltaPos)); longRange = proj_GetLongRange(psStats); /* modification by CorvusCorax - calculate shooting angle */ int min_angle = 0; // only calculate for indirect shots if (!proj_Direct(psStats) && dist > 0) { min_angle = arcOfFire(psAttacker,psTarget,weapon_slot,true); // prevent extremely steep shots min_angle = std::min(min_angle, DEG(PROJ_ULTIMATE_PITCH)); // adjust maximum range of unit if forced to shoot very steep if (min_angle > DEG(PROJ_MAX_PITCH)) { //do not allow increase of max range though if (iSin(2*min_angle) < iSin(2*DEG(PROJ_MAX_PITCH))) // If PROJ_MAX_PITCH == 45, then always iSin(2*min_angle) <= iSin(2*DEG(PROJ_MAX_PITCH)), and the test is redundant. { longRange = longRange * iSin(2*min_angle) / iSin(2*DEG(PROJ_MAX_PITCH)); } } } int baseHitChance = 0; if ((dist <= psStats->shortRange) && (dist >= psStats->minRange)) { // get weapon chance to hit in the short range baseHitChance = weaponShortHit(psStats,psAttacker->player); } else if ((dist <= longRange && dist >= psStats->minRange) || (psAttacker->type == OBJ_DROID && !proj_Direct(psStats) && actionInsideMinRange(psDroid, psTarget, psStats))) { // get weapon chance to hit in the long range baseHitChance = weaponLongHit(psStats,psAttacker->player); // adapt for height adjusted artillery shots if (min_angle > DEG(PROJ_MAX_PITCH)) { baseHitChance = baseHitChance * iCos(min_angle) / iCos(DEG(PROJ_MAX_PITCH)); } } else { /* Out of range */ objTrace(psAttacker->id, "combFire(%u[%s]->%u): Out of range", psAttacker->id, psStats->pName, psTarget->id); return false; } // apply experience accuracy modifiers to the base //hit chance, not to the final hit chance int resultHitChance = baseHitChance; // add the attacker's experience if (psAttacker->type == OBJ_DROID) { SDWORD level = getDroidEffectiveLevel((DROID *) psAttacker); // increase total accuracy by EXP_ACCURACY_BONUS % for each experience level resultHitChance += EXP_ACCURACY_BONUS * level * baseHitChance / 100; } // subtract the defender's experience if (psTarget->type == OBJ_DROID) { SDWORD level = getDroidEffectiveLevel((DROID *) psTarget); // decrease weapon accuracy by EXP_ACCURACY_BONUS % for each experience level resultHitChance -= EXP_ACCURACY_BONUS * level * baseHitChance / 100; } // fire while moving modifiers if (psAttacker->type == OBJ_DROID && ((DROID *)psAttacker)->sMove.Status != MOVEINACTIVE) { switch (psStats->fireOnMove) { case FOM_NO: // Can't fire while moving return false; break; case FOM_PARTIAL: resultHitChance = FOM_PARTIAL_ACCURACY_PENALTY * resultHitChance / 100; break; case FOM_YES: // can fire while moving break; } } /* -------!!! From that point we are sure that we are firing !!!------- */ /* note when the weapon fired */ psWeap->lastFired = gameTime; /* reduce ammo if salvo */ if (psStats->reloadTime) { psWeap->ammo--; } // increment the shots counter psWeap->shotsFired++; // predicted X,Y offset per sec Vector3i predict = psTarget->pos; //Watermelon:Target prediction if (isDroid(psTarget)) { DROID *psDroid = castDroid(psTarget); int32_t flightTime; if (proj_Direct(psStats) || dist <= psStats->minRange) { flightTime = dist / psStats->flightSpeed; } else { int32_t vXY, vZ; // Unused, we just want the flight time. flightTime = projCalcIndirectVelocities(dist, deltaPos.z, psStats->flightSpeed, &vXY, &vZ, min_angle); } if (psTarget->lastHitWeapon == WSC_EMP) { int empTime = EMP_DISABLE_TIME - (gameTime - psTarget->timeLastHit); CLIP(empTime, 0, EMP_DISABLE_TIME); if (empTime >= EMP_DISABLE_TIME * 9/10) { flightTime = 0; /* Just hit. Assume they'll get hit again */ } else { flightTime = MAX(0, flightTime - empTime); } } predict += Vector3i(iSinCosR(psDroid->sMove.moveDir, psDroid->sMove.speed*flightTime / GAME_TICKS_PER_SEC), 0); } /* Fire off the bullet to the miss location. The miss is only visible if the player owns the target. (Why? - Per) */ // What bVisible really does is to make the projectile audible even if it misses you. Since the target is NULL, proj_SendProjectile can't check if it was fired at you. bool bVisibleAnyway = psTarget->player == selectedPlayer; // see if we were lucky to hit the target bool isHit = gameRand(100) <= resultHitChance; if (isHit) { /* Kerrrbaaang !!!!! a hit */ objTrace(psAttacker->id, "combFire: [%s]->%u: resultHitChance=%d, visibility=%hhu : ", psStats->pName, psTarget->id, resultHitChance, psTarget->visible[psAttacker->player]); syncDebug("hit=(%d,%d,%d)", predict.x, predict.y, predict.z); } else /* Deal with a missed shot */ { const int minOffset = 5; int missDist = 2 * (100 - resultHitChance) + minOffset; Vector3i miss = Vector3i(iSinCosR(gameRand(DEG(360)), missDist), 0); predict += miss; psTarget = NULL; // Missed the target, so don't expect to hit it. objTrace(psAttacker->id, "combFire: Missed shot by (%4d,%4d)", miss.x, miss.y); syncDebug("miss=(%d,%d,%d)", predict.x, predict.y, predict.z); } // Make sure we don't pass any negative or out of bounds numbers to proj_SendProjectile CLIP(predict.x, 0, world_coord(mapWidth - 1)); CLIP(predict.y, 0, world_coord(mapHeight - 1)); proj_SendProjectileAngled(psWeap, psAttacker, psAttacker->player, predict, psTarget, bVisibleAnyway, weapon_slot, min_angle); return true; }
int main( _In_ int argc, _In_ TCHAR * argv[] ) { DWORD i = 0; LOG(Succ, _T("Starting")); // // Options parsing // LOG(Succ, _T("Parsing options")); ACE_FILTER_OPTIONS options = { 0 }; DWORD importerAce = PLUGIN_MAX_IMPORTERS; DWORD importerObj = PLUGIN_MAX_IMPORTERS; DWORD importerSch = PLUGIN_MAX_IMPORTERS; if (argc > 1) { ParseOptions(&options, argc, argv); } else { options.misc.showHelp = TRUE; } if (options.misc.showHelp) { Usage(argv[0], NULL); ForeachLoadedPlugins(&options, PluginHelp); ExitProcess(EXIT_FAILURE); } // // Plugins verifications // LOG(Succ, "Verifying and choosing plugins"); if (options.plugins.numberOfImporters == 0){ FATAL(_T("No importer has been loaded")); } if (options.plugins.numberOfWriters == 0){ FATAL(_T("No writer has been loaded")); } for (i = 0; i < options.plugins.numberOfImporters; i++) { if (!PLUGIN_IS_LOADED(&options.plugins.importers[i])) { FATAL(_T("Importer <%u> is registered, but not loaded"), i); } if (importerAce == PLUGIN_MAX_IMPORTERS && options.plugins.importers[i].functions.GetNextAce) { LOG(Info, SUB_LOG(_T("Using <%s> to import ACE")), PLUGIN_GET_NAME(&options.plugins.importers[i])); importerAce = i; } if (importerObj == PLUGIN_MAX_IMPORTERS && options.plugins.importers[i].functions.GetNextSchema) { LOG(Info, SUB_LOG(_T("Using <%s> to import objects")), PLUGIN_GET_NAME(&options.plugins.importers[i])); importerObj = i; } if (importerSch == PLUGIN_MAX_IMPORTERS && options.plugins.importers[i].functions.GetNextObject) { LOG(Info, SUB_LOG(_T("Using <%s> to import schema")), PLUGIN_GET_NAME(&options.plugins.importers[i])); importerSch = i; } } if (importerAce == PLUGIN_MAX_IMPORTERS){ FATAL(_T("ACE importer is missing")); } if (importerObj == PLUGIN_MAX_IMPORTERS){ FATAL(_T("Obj importer is missing")); } if (importerSch == PLUGIN_MAX_IMPORTERS){ FATAL(_T("Sch importer is missing")); } // We allow no filter to be loaded, to permit ACE format conversion (direct link importer->writer) if (options.plugins.numberOfFilters > 0) { for (i = 0; i < options.plugins.numberOfFilters; i++) { if (!PLUGIN_IS_LOADED(&options.plugins.filters[i])) { FATAL(_T("Filter <%u> is registered, but not loaded"), i); } } } for (i = 0; i < options.plugins.numberOfWriters; i++) { if (!PLUGIN_IS_LOADED(&options.plugins.writers[i])) { FATAL(_T("Writer <%u> is registered, but not loaded"), i); } } // // Initializing plugins // LOG(Succ, _T("Initializing plugins")); ForeachLoadedPlugins(&options, PluginInitialize); // // Constructing caches // LOG(Succ, _T("Constructing caches")); CachesInitialize(); if (PluginsRequires(&options, OPT_REQ_SID_RESOLUTION) || PluginsRequires(&options, OPT_REQ_DN_RESOLUTION)) { LOG(Info, SUB_LOG(_T("Plugins require SID or DN resolution, constructing object cache"))); ConstructObjectCache(&options.plugins.importers[importerObj]); LOG(Info, SUB_LOG(_T("Object cache count : <by-sid:%u> <by-dn:%u>")), CacheObjectBySidCount(), CacheObjectByDnCount()); } if (PluginsRequires(&options, OPT_REQ_GUID_RESOLUTION) || PluginsRequires(&options, OPT_REQ_CLASSID_RESOLUTION) || PluginsRequires(&options, OPT_REQ_DISPLAYNAME_RESOLUTION)) { LOG(Info, SUB_LOG(_T("Plugins require GUID or CLASSID or DisplayName resolution, constructing schema cache"))); ConstructSchemaCache(&options.plugins.importers[importerSch]); LOG(Info, SUB_LOG(_T("Schema cache count : <by-guid:%u> <by-classid:%u> <by-displayname:%u>")), CacheSchemaByGuidCount(), CacheSchemaByClassidCount(), CacheSchemaByDisplayNameCount()); } if (PluginsRequires(&options, OPT_REQ_ADMINSDHOLDER_SD)) { LOG(Info, SUB_LOG(_T("Plugins require AdminSdHolder security descriptor, constructing it"))); ConstructAdminSdHolderSD(&options.plugins.importers[importerAce]); } // // Main Loop : process and filter ACEs // LOG(Succ, _T("Starting ACE filtering")); IMPORTED_ACE ace = { 0 }; BOOL passedFilters = TRUE; BOOL filterRet = FALSE; // Stats variables DWORD aceCount = 0; DWORD keptAceCount = 0; ULONGLONG timeStart = 0; timeStart = GetTickCount64(); options.plugins.importers[importerAce].functions.ResetReading(&gc_PluginApiTable, ImporterAce); while (options.plugins.importers[importerAce].functions.GetNextAce(&gc_PluginApiTable, &ace)) { passedFilters = TRUE; ace.computed.number = ++aceCount; for (i = 0; i < options.plugins.numberOfFilters; i++) { filterRet = options.plugins.filters[i].functions.FilterAce(&gc_PluginApiTable, &ace); passedFilters &= options.plugins.filters[i].inverted ? !filterRet : filterRet; if (!passedFilters) { LOG(All, _T("Ace <%u> was filtered by <%s>"), aceCount, PLUGIN_GET_NAME(&options.plugins.filters[i])); break; } } if (passedFilters) { keptAceCount++; LOG(All, _T("Ace <%u> passed all filters"), aceCount); for (i = 0; i < options.plugins.numberOfWriters; i++) { options.plugins.writers[i].functions.WriteAce(&gc_PluginApiTable, &ace); } } if (aceCount % options.misc.progression == 0) { LOG(Info, SUB_LOG(_T("Count : %u")), aceCount); } FreeCheckX(ace.imported.objectDn); // TODO : possible leak, since this is importer-dependant. Call importer's destroyer instead. LocalFreeCheckX(ace.imported.raw); ZeroMemory(&ace, sizeof(IMPORTED_ACE)); } // // Stats // LOG(Succ, _T("Done. ACE Statistics :")); LOG(Succ, SUB_LOG(_T("<total : %u>")), aceCount); LOG(Succ, SUB_LOG(_T("<filtered : %06.2f%% %u>")), PERCENT((aceCount - keptAceCount), aceCount), (aceCount - keptAceCount)); LOG(Succ, SUB_LOG(_T("<kept : %06.2f%% %u>")), PERCENT(keptAceCount, aceCount), keptAceCount); LOG(Succ, SUB_LOG(_T("<time : %.3fs>")), TIME_DIFF_SEC(timeStart, GetTickCount64())); // // Finalizing and unloading plugins // LOG(Succ, _T("Finalizing and unloading plugins")); ForeachLoadedPlugins(&options, PluginFinalize); ForeachLoadedPlugins(&options, PluginUnload); CachesDestroy(); DestroyStrPairList(gs_PluginOptions.head); // // End // LOG(Succ, _T("Done")); return EXIT_SUCCESS; }