📄 npccgi.c
字号:
strcpy( buffer, dndGetClassName( cls->type ) ); buffer[0] = toupper( buffer[0] ); wtPrint( stream, "<TR><TD CLASS=\"DIVIDER\" COLSPAN=2><IMG SRC=\"/img/blank.gif\" WIDTH=1 HEIGHT=1></TD></TR>" ); wtPrintf( stream, "<TR><TD CLASS=\"HEADER\" COLSPAN=2>%s Spells Per Day:</TD></TR>\n", buffer ); if( relevantAbility < 11 ) { wtPrintf( stream, "<TR><TD CLASS=\"NORMAL\" COLSPAN=2>This character is unable to cast any %s spells, due to an unfortunately low relevant ability score.</TD></TR>\n", dndGetClassName( cls->type ) ); continue; } total = 0; maxLevel = relevantAbility - 10; if( maxLevel > 9 ) { maxLevel = 9; } if( maxLevel < 0 ) { maxLevel = 0; } for( i = 0; i <= maxLevel; i++ ) { count = dndGetSpellsPerDay( cls->type, cls->level, i ); if( count < 0 ) { continue; } count += dndGetBonusSpellsPerDay( relevantAbility, i ); if( count < 1 ) { continue; } total += count; wtPrintf( stream, "<TR><TD CLASS=\"NORMAL\" ALIGN=\"RIGHT\"><B>%d</B>%s-level:</TD><TD CLASS=\"NORMAL\"><B>%d%s</B> (DC %d where applicable)</TD></TR>\n", i, getOrdinalSuffix( i ), count, ( ( hasPlus && i > 0 ) ? "+1" : "" ), 10 + i + dndGetAbilityBonus( relevantAbility ) ); if( ( hasPlus ) && ( i > 0 ) ) { total++; } if( list != 0 ) { wtPrint( stream, "<TR><TD CLASS=\"NORMAL\"> </TD><TD CLASS=\"NORMAL\">\n<UL>\n" ); for( spell = list[ i ]; spell != 0; spell = spell->next ) { wtPrintf( stream, "<LI>%s\n", dndGetSpellName( spell->spell ) ); } wtPrint( stream, "</UL>\n</TD></TR>\n" ); } } if( total > 0 ) { wtPrintf( stream, "<TR><TD CLASS=\"DATA\" ALIGN=\"RIGHT\">Total:</TD><TD CLASS=\"DATA\">%d</TD></TR>\n", total ); } else { wtPrintf( stream, "<TR><TD CLASS=\"NORMAL\" COLSPAN=2>This character is unable to cast any %s spells until they attain a higher level.</TD></TR>\n", dndGetClassName( cls->type ) ); } } return 0;}int displayAttacks( wtSTREAM_t* stream, wtTAG_t** tags, wtGENERIC_t data, char* other ) { NPC* npc; int baseAttack; int attackCount; int attack; int i; int bonus; NPCCOMPBREAKDOWN* breakdown; char buffer[512]; npc = (NPC*)data; baseAttack = npcGetBaseAttack( npc ); /* multiple attacks are based on the unmodified base attack */ attackCount = dndGetClassAttacksPerRound( baseAttack ); /* get the modified attack bonus */ attack = npcComputeActualAttack( npc, attMELEE, &breakdown ); wtPrint( stream, "<TR><TD CLASS=\"NORMAL\">Melee:</TD><TD CLASS=\"DATA\">" ); for( i = 1; i <= attackCount; i++ ) { if( i > 1 ) { wtPrint( stream, "/" ); } bonus = dndGetClassMultipleAttackBonus( attack, i ); wtPrintf( stream, "%+d", bonus ); } wtPrintf( stream, " %s</TD></TR>\n", npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); if( npcHasClass( npc, pcMONK ) ) { int monkAttackCount; int monkBaseAttack; NPCCLASS* cls; cls = npcGetClass( npc, pcMONK ); monkBaseAttack = dndGetClassAttackBonus( pcMONK, cls->level ) + dndGetRaceBonus( npc->race, npc->gender, rbtATTACK, 0 ); monkAttackCount = dndGetMonkAttacksPerRound( monkBaseAttack ); attack = npcComputeActualAttack( npc, attMELEE, &breakdown ); wtPrint( stream, "<TR><TD CLASS=\"NORMAL\">Monk:</TD><TD CLASS=\"DATA\">" ); for( i = 1; i <= monkAttackCount; i++ ) { if( i > 1 ) { wtPrint( stream, "/" ); } bonus = dndGetMonkMultipleAttackBonus( attack, i ); wtPrintf( stream, "%+d", bonus ); } wtPrintf( stream, " %s</TD></TR>\n", npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); } attack = npcComputeActualAttack( npc, attRANGED, &breakdown ); wtPrint( stream, "<TR><TD CLASS=\"NORMAL\">Ranged:</TD><TD CLASS=\"DATA\">" ); for( i = 1; i <= attackCount; i++ ) { if( i > 1 ) { wtPrint( stream, "/" ); } bonus = dndGetClassMultipleAttackBonus( attack, i ); wtPrintf( stream, "%+d", bonus ); } wtPrintf( stream, " %s</TD></TR>\n", npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); return 0;}int displayNPC_StatBlock( wtSTREAM_t *stream, NPC** npc ) { char statBlock[4096]; int count; int i; int doBg; NPCSTATBLOCKOPTS opts; char motivation1[ 1024 ]; char motivation2[ 1024 ]; grGRAMMAR* grammar; doBg = ( *qValueDefault( "", "background" ) == 'Y' ); if( doBg ) { grammar = openNPCMotivationGrammar( TEMPATH ); } count = qiValue( "count" ); if( count < 1 ) { count = 1; } if( count > 100 ) { count = 100; } wtPrint( stream, "<DIV CLASS=\"NORMAL\">\n" ); if( !qiValue( "printable" ) ) { wtPrintf( stream, "<A HREF=\"%s&printable=1\" TARGET=\"PRINT\">Open printable version</A>\n<P>", url ); } memset( &opts, 0, sizeof( opts ) ); opts.abilityBonuses = qiValue( "stats_ability_bonuses" ); opts.acBreakdown = qiValue( "stats_ac_breakdown" ); opts.initBreakdown = qiValue( "stats_init_breakdown" ); opts.attackBreakdown = qiValue( "stats_attack_breakdown" ); opts.saveBreakdown = qiValue( "stats_save_breakdown" ); opts.skillBreakdown = qiValue( "stats_skill_breakdown" ); opts.languages = qiValue( "stats_languages" ); opts.skillsAndFeats = qiValue( "stats_skillsfeats" ); opts.possessions = qiValue( "stats_possessions" ); opts.spells = qiValue( "stats_spells" ); opts.richFormatting = qiValue( "stats_formatting" ); for( i = 0; i < count; i++ ) { npcBuildStatBlock( npc[i], &opts, statBlock, sizeof( statBlock ) ); strrepl( statBlock, "~B", "<B>" ); strrepl( statBlock, "~b", "</B>" ); strrepl( statBlock, "\n", "<BR>\n" ); strrepl( statBlock, "~I", "<I>" ); strrepl( statBlock, "~i", "</I>" ); wtPrint( stream, statBlock ); if( doBg ) { grammar->startSymbol = "[motivation]"; getNPCMotivation( grammar, npc[i], motivation1, sizeof( motivation1 ) ); do { getNPCMotivation( grammar, npc[i], motivation2, sizeof( motivation1 ) ); } while( strcmp( motivation1, motivation2 ) == 0 ); wtPrintf( stream, "<P><I>Primary motivation:</I> %s\n", motivation1 ); wtPrintf( stream, "<P><I>Secondary motivation:</I> %s\n", motivation2 ); getNPCRecentPast( grammar, npc[i], motivation1, sizeof( motivation1 ) ); wtPrintf( stream, "<P><I>Recent Past:</I> %s\n", motivation1 ); } if( i+1 < count ) { wtPrint( stream, "\n<HR SIZE=1>\n" ); } } wtPrint( stream, "</DIV>\n<P>\n" ); if( doBg ) { grDestroyGrammar( grammar ); } return 0;}int displayLanguages( wtSTREAM_t* stream, wtTAG_t** tags, wtGENERIC_t data, char* other ) { NPC* npc; NPCLANGUAGE* lang; char text[128]; npc = (NPC*)data; wtPrint( stream, "<TR><TD CLASS=\"NORMAL\" COLSPAN=2>\n" ); wtPrint( stream, "<UL>\n" ); for( lang = npc->languages; lang != 0; lang = lang->next ) { strcpy( text, dndGetLanguageName( lang->language ) ); text[0] = toupper( text[0] ); wtPrintf( stream, "<LI>%s\n", text ); } wtPrint( stream, "</UL>\n" ); wtPrint( stream, "</TD></TR>\n" ); return 0;}int displayNPCBackground( wtSTREAM_t* stream, wtTAG_t** tags, wtGENERIC_t data, char* other ) { grGRAMMAR* grammar; NPC* npc; char m1[1024]; char m2[1024]; npc = (NPC*)data; if( *qValueDefault( "", "background" ) == 'Y' ) { grammar = openNPCMotivationGrammar( TEMPATH ); grammar->startSymbol = "[motivation]"; getNPCMotivation( grammar, npc, m1, sizeof( m1 ) ); do { getNPCMotivation( grammar, npc, m2, sizeof( m2 ) ); } while( strcmp( m1, m2 ) == 0 ); wtPrint( stream, "<TR><TD CLASS=\"DIVIDER\" COLSPAN=2><IMG SRC=\"/img/blank.gif\" WIDTH=1 HEIGHT=1></TD></TR>\n" ); wtPrint( stream, "<TR><TD CLASS=\"NORMAL\" COLSPAN=2>\n" ); wtPrintf( stream, "<B>Primary Motivation:</B> %s\n<P>\n", m1 ); wtPrintf( stream, "<B>Secondary Motivation:</B> %s\n<P>\n", m2 ); getNPCRecentPast( grammar, npc, m1, sizeof( m1 ) ); wtPrintf( stream, "<B>Recent Past:</B> %s\n", m1 ); wtPrint( stream, "</TD></TR>" ); grDestroyGrammar( grammar ); } return 0;}int displayNPC_Full( wtSTREAM_t* stream, NPC* npc ) { wtTAG_t *tags[37]; char alignment[20]; char race[40]; char gender[20]; wtDELEGATE_t d_skill; wtDELEGATE_t d_feat; wtDELEGATE_t d_class; wtDELEGATE_t d_spells; wtDELEGATE_t d_attack; wtDELEGATE_t d_languages; wtDELEGATE_t d_background; char strbonus[5]; char dexbonus[5]; char conbonus[5]; char intbonus[5]; char wisbonus[5]; char chabonus[5]; char height[100]; char weight[100]; int armorClass; char armorClassTxt[ 256 ]; int useWisdom; int initiative; char initiativeTxt[ 256 ]; int save; int cr; int speed; char fortSave[100]; char refSave[100]; char willSave[100]; char gearValue[100]; char buffer[ 512 ]; char pcgen[ 1024 ]; char hpDesc[ 512 ]; NPCCOMPBREAKDOWN* breakdown; NPCCLASS* cls; char* tem; strcpy( alignment, dndGetAlignmentText( npc->alignment ) ); alignment[0] = toupper( alignment[0] ); strcpy( race, (char*)dndGetRaceName( npc->race ) ); race[0] = toupper( race[0] ); strcpy( gender, ( npc->gender == gMALE ? "Male" : "Female" ) ); /* compute the armor class, and build the text describing how we arrived * at this number */ armorClass = npcComputeActualAC( npc, &breakdown ); sprintf( armorClassTxt, "%d %s", armorClass, npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); /* compute the initiative score, and build the text describing how we * arrived at this number */ initiative = npcComputeActualInitiative( npc, &breakdown ); sprintf( initiativeTxt, "%+d %s", initiative, npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); /* calculate the ability bonuses */ sprintf( strbonus, "%+d", dndGetAbilityBonus( npc->strength ) ); sprintf( dexbonus, "%+d", dndGetAbilityBonus( npc->dexterity ) ); sprintf( conbonus, "%+d", dndGetAbilityBonus( npc->constitution ) ); sprintf( intbonus, "%+d", dndGetAbilityBonus( npc->intelligence ) ); sprintf( wisbonus, "%+d", dndGetAbilityBonus( npc->wisdom ) ); sprintf( chabonus, "%+d", dndGetAbilityBonus( npc->charisma ) ); npcBuildHitDiceBreakdown( npc, hpDesc, sizeof( hpDesc ) ); sprintf( &(hpDesc[strlen(hpDesc)]), " (%d)", npc->hp ); cr = npcComputeCR( npc ); speed = dndGetRaceSpeed( npc->race ); if( npcHasClass( npc, pcBARBARIAN ) ) { speed += 10; } cls = npcGetClass( npc, pcMONK ); if( cls != 0 ) { save = dndGetMonkSpeedForRace( npc->race, cls->level ); if( save > speed ) { speed = save; } } /* set up the tags that will be written out */ tags[0] = wtTagReplace( "ALIGNMENT", alignment ); tags[1] = wtTagReplace( "RACE", race ); tags[2] = wtTagReplace( "GENDER", gender ); tags[3] = wtTagReplaceI( "STRENGTH", npc->strength ); tags[4] = wtTagReplaceI( "DEXTERITY", npc->dexterity ); tags[5] = wtTagReplaceI( "CONSTITUTION", npc->constitution ); tags[6] = wtTagReplaceI( "INTELLIGENCE", npc->intelligence ); tags[7] = wtTagReplaceI( "WISDOM", npc->wisdom ); tags[8] = wtTagReplaceI( "CHARISMA", npc->charisma ); tags[9] = wtTagReplace( "STRBONUS", strbonus ); tags[10] = wtTagReplace( "DEXBONUS", dexbonus ); tags[11] = wtTagReplace( "CONBONUS", conbonus ); tags[12] = wtTagReplace( "INTBONUS", intbonus ); tags[13] = wtTagReplace( "WISBONUS", wisbonus ); tags[14] = wtTagReplace( "CHABONUS", chabonus ); tags[15] = wtTagReplace( "HP", hpDesc ); d_skill.handler = displaySkills; d_skill.userData = npc; d_feat.handler = displayFeats; d_feat.userData = npc->feats; d_class.handler = displayClasses; d_class.userData = npc->classes; d_spells.handler = displaySpells; d_spells.userData = npc; d_attack.handler = displayAttacks; d_attack.userData = npc; d_languages.handler = displayLanguages; d_languages.userData = npc; d_background.handler = displayNPCBackground; d_background.userData = npc; tags[16] = wtTagDelegate( "SKILLS", &d_skill ); tags[17] = wtTagDelegate( "FEATS", &d_feat ); tags[18] = wtTagDelegate( "CLASSES", &d_class ); tags[19] = wtTagReplace( "AC", armorClassTxt ); tags[20] = wtTagReplace( "INIT", initiativeTxt ); tags[21] = wtTagDelegate( "SPELLS", &d_spells ); tags[22] = wtTagDelegate( "ATTACK", &d_attack ); /* compute and format the saving throws */ save = npcComputeActualSave( npc, svFORTITUDE, &breakdown ); sprintf( fortSave, "%+d %s", save, npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); save = npcComputeActualSave( npc, svREFLEX, &breakdown ); sprintf( refSave, "%+d %s", save, npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); save = npcComputeActualSave( npc, svWILL, &breakdown ); sprintf( willSave, "%+d %s", save, npcBuildComponentBreakdownDescription( breakdown, buffer, sizeof( buffer ) ) ); npcDestroyComponentBreakdown( breakdown ); /* compute and format the gp value of the NPC's gear */ commify( gearValue, npcGearValue( npc ) ); strcat( gearValue, " gp" ); /* if we are not displaying the "printable" version, put up a link to * allow a printable version to be displayed. */ if( !qiValue( "printable" ) ) { sprintf( buffer, "<A HREF=\"%s&printable=1\" TARGET=\"PRINT\">Open printable version</A>", url ); sprintf( pcgen, "<A HREF=\"%s&action=pcgen\" TARGET=\"PCGEN\">Download in PCGen Format</a><br>" "(<span style=\"color: red\">EXPERIMENTAL</span>) " "[ <a href=\"javascript:pcgenHelp()\">What is this</a>? ]", url ); } else { buffer[0] = 0; pcgen[0] = 0; } /* format the height and weight */ if( npc->height_in > 0 ) { sprintf( height, "%d' %d\" ", npc->height_ft, npc->height_in ); } else { sprintf( height, "%d'", npc->height_ft ); } commify( weight, npc->weight ); strcat( weight, " lbs" ); tags[23] = wtTagReplace( "FORTSAVE", fortSave ); tags[24] = wtTagReplace( "REFSAVE", refSave ); tags[25] = wtTagReplace( "WILLSAVE", willSave ); tags[26] = wtTagReplace( "GEARVALUE", gearValue ); tags[27] = wtTagReplace( "DOPRINTABLE", buffer ); tags[28] = wtTagReplace( "HEIGHT", height ); tags[29] = wtTagReplace( "WEIGHT", weight ); tags[30] = wtTagReplaceI( "CR", cr ); tags[31] = wtTagReplace( "NAME", npc->name ); tags[32] = wtTagDelegate( "LANGUAGES", &d_languages ); tags[33] = wtTagReplaceI( "SPEED", speed ); tags[34] = wtTagDelegate( "BACKGROUND", &d_background );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -