AGS: Move character.cpp globals to Globals

This commit is contained in:
Paul Gilbert 2021-03-08 19:04:35 -08:00
parent f05ad88320
commit dc019af530
31 changed files with 348 additions and 429 deletions

View File

@ -85,29 +85,6 @@ extern Bitmap **actsps;
extern int said_speech_line;
extern int said_text;
//--------------------------------
CharacterExtras *charextra;
CharacterInfo *playerchar;
int32_t _sc_PlayerCharPtr = 0;
int char_lowest_yp;
// Sierra-style speech settings
int face_talking = -1, facetalkview = 0, facetalkwait = 0, facetalkframe = 0;
int facetalkloop = 0, facetalkrepeat = 0, facetalkAllowBlink = 1;
int facetalkBlinkLoop = 0;
CharacterInfo *facetalkchar = nullptr;
// Do override default portrait position during QFG4-style speech overlay update
bool facetalk_qfg4_override_placement_x = false;
bool facetalk_qfg4_override_placement_y = false;
// lip-sync speech settings
int loops_per_character, text_lips_offset, char_speaking = -1;
int char_thinking = -1;
const char *text_lips_text = nullptr;
SpeechLipSyncLine *splipsync = nullptr;
int numLipLines = 0, curLipLine = -1, curLipLinePhoneme = 0;
// **** CHARACTER: FUNCTIONS ****
void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addIndex) {
@ -127,33 +104,33 @@ void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addInd
if (_GP(game).options[OPT_DUPLICATEINV] == 0) {
// Ensure it is only in the list once
for (ee = 0; ee < charextra[charid].invorder_count; ee++) {
if (charextra[charid].invorder[ee] == inum) {
for (ee = 0; ee < _G(charextra)[charid].invorder_count; ee++) {
if (_G(charextra)[charid].invorder[ee] == inum) {
// They already have the item, so don't add it to the list
if (chaa == playerchar)
if (chaa == _G(playerchar))
run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
return;
}
}
}
if (charextra[charid].invorder_count >= MAX_INVORDER)
if (_G(charextra)[charid].invorder_count >= MAX_INVORDER)
quit("!Too many inventory items added, max 500 display at one time");
if ((addIndex == SCR_NO_VALUE) ||
(addIndex >= charextra[charid].invorder_count) ||
(addIndex >= _G(charextra)[charid].invorder_count) ||
(addIndex < 0)) {
// add new item at end of list
charextra[charid].invorder[charextra[charid].invorder_count] = inum;
_G(charextra)[charid].invorder[_G(charextra)[charid].invorder_count] = inum;
} else {
// insert new item at index
for (ee = charextra[charid].invorder_count - 1; ee >= addIndex; ee--)
charextra[charid].invorder[ee + 1] = charextra[charid].invorder[ee];
for (ee = _G(charextra)[charid].invorder_count - 1; ee >= addIndex; ee--)
_G(charextra)[charid].invorder[ee + 1] = _G(charextra)[charid].invorder[ee];
charextra[charid].invorder[addIndex] = inum;
_G(charextra)[charid].invorder[addIndex] = inum;
}
charextra[charid].invorder_count++;
_G(charextra)[charid].invorder_count++;
guis_need_update = 1;
if (chaa == playerchar)
if (chaa == _G(playerchar))
run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
}
@ -297,7 +274,7 @@ void Character_ChangeView(CharacterInfo *chap, int vii) {
chap->frame = 0;
chap->wait = 0;
chap->walkwait = 0;
charextra[chap->index_id].animwait = 0;
_G(charextra)[chap->index_id].animwait = 0;
FindReasonableLoopForCharacter(chap);
}
@ -677,7 +654,7 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
if ((chap->activeinv == inum) & (chap->inv[inum] < 1)) {
chap->activeinv = -1;
if ((chap == playerchar) && (GetCursorMode() == MODE_USE))
if ((chap == _G(playerchar)) && (GetCursorMode() == MODE_USE))
set_cursor_mode(0);
}
@ -685,18 +662,18 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
if ((chap->inv[inum] == 0) || (_GP(game).options[OPT_DUPLICATEINV] > 0)) {
int xx, tt;
for (xx = 0; xx < charextra[charid].invorder_count; xx++) {
if (charextra[charid].invorder[xx] == inum) {
charextra[charid].invorder_count--;
for (tt = xx; tt < charextra[charid].invorder_count; tt++)
charextra[charid].invorder[tt] = charextra[charid].invorder[tt + 1];
for (xx = 0; xx < _G(charextra)[charid].invorder_count; xx++) {
if (_G(charextra)[charid].invorder[xx] == inum) {
_G(charextra)[charid].invorder_count--;
for (tt = xx; tt < _G(charextra)[charid].invorder_count; tt++)
_G(charextra)[charid].invorder[tt] = _G(charextra)[charid].invorder[tt + 1];
break;
}
}
}
guis_need_update = 1;
if (chap == playerchar)
if (chap == _G(playerchar))
run_on_event(GE_LOSE_INV, RuntimeScriptValue().SetInt32(inum));
}
@ -766,7 +743,7 @@ void Character_SetAsPlayer(CharacterInfo *chaa) {
//update_invorder();
debug_script_log("%s is new player character", playerchar->scrname);
debug_script_log("%s is new player character", _G(playerchar)->scrname);
// Within game_start, return now
if (_G(displayed_room) < 0)
@ -775,23 +752,23 @@ void Character_SetAsPlayer(CharacterInfo *chaa) {
// Ignore invalid room numbers for the character and just place him in
// the current room for 2.x. Following script calls to NewRoom() will
// make sure this still works as intended.
if ((loaded_game_file_version <= kGameVersion_272) && (playerchar->room < 0))
playerchar->room = _G(displayed_room);
if ((loaded_game_file_version <= kGameVersion_272) && (_G(playerchar)->room < 0))
_G(playerchar)->room = _G(displayed_room);
if (_G(displayed_room) != playerchar->room)
NewRoom(playerchar->room);
if (_G(displayed_room) != _G(playerchar)->room)
NewRoom(_G(playerchar)->room);
else // make sure it doesn't run the region interactions
_GP(play).player_on_region = GetRegionIDAtRoom(playerchar->x, playerchar->y);
_GP(play).player_on_region = GetRegionIDAtRoom(_G(playerchar)->x, _G(playerchar)->y);
if ((playerchar->activeinv >= 0) && (playerchar->inv[playerchar->activeinv] < 1))
playerchar->activeinv = -1;
if ((_G(playerchar)->activeinv >= 0) && (_G(playerchar)->inv[_G(playerchar)->activeinv] < 1))
_G(playerchar)->activeinv = -1;
// They had inv selected, so change the cursor
if (cur_mode == MODE_USE) {
if (playerchar->activeinv < 0)
if (_G(playerchar)->activeinv < 0)
SetNextCursor();
else
SetActiveInventory(playerchar->activeinv);
SetActiveInventory(_G(playerchar)->activeinv);
}
}
@ -828,7 +805,7 @@ void Character_SetIdleView(CharacterInfo *chaa, int iview, int itime) {
}
// if they switch to a swimming animation, kick it off immediately
if (itime == 0)
charextra[chaa->index_id].process_idle_this_time = 1;
_G(charextra)[chaa->index_id].process_idle_this_time = 1;
}
@ -837,35 +814,35 @@ bool Character_GetHasExplicitLight(CharacterInfo *ch) {
}
int Character_GetLightLevel(CharacterInfo *ch) {
return ch->has_explicit_light() ? charextra[ch->index_id].tint_light : 0;
return ch->has_explicit_light() ? _G(charextra)[ch->index_id].tint_light : 0;
}
void Character_SetLightLevel(CharacterInfo *chaa, int light_level) {
light_level = Math::Clamp(light_level, -100, 100);
charextra[chaa->index_id].tint_light = light_level;
_G(charextra)[chaa->index_id].tint_light = light_level;
chaa->flags &= ~CHF_HASTINT;
chaa->flags |= CHF_HASLIGHT;
}
int Character_GetTintRed(CharacterInfo *ch) {
return ch->has_explicit_tint() ? charextra[ch->index_id].tint_r : 0;
return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_r : 0;
}
int Character_GetTintGreen(CharacterInfo *ch) {
return ch->has_explicit_tint() ? charextra[ch->index_id].tint_g : 0;
return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_g : 0;
}
int Character_GetTintBlue(CharacterInfo *ch) {
return ch->has_explicit_tint() ? charextra[ch->index_id].tint_b : 0;
return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_b : 0;
}
int Character_GetTintSaturation(CharacterInfo *ch) {
return ch->has_explicit_tint() ? charextra[ch->index_id].tint_level : 0;
return ch->has_explicit_tint() ? _G(charextra)[ch->index_id].tint_level : 0;
}
int Character_GetTintLuminance(CharacterInfo *ch) {
return ch->has_explicit_tint() ? ((charextra[ch->index_id].tint_light * 10) / 25) : 0;
return ch->has_explicit_tint() ? ((_G(charextra)[ch->index_id].tint_light * 10) / 25) : 0;
}
void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno) {
@ -908,10 +885,10 @@ void Character_StopMoving(CharacterInfo *charp) {
if (chaa == _GP(play).skip_until_char_stops)
EndSkippingUntilCharStops();
if (charextra[chaa].xwas != INVALID_X) {
charp->x = charextra[chaa].xwas;
charp->y = charextra[chaa].ywas;
charextra[chaa].xwas = INVALID_X;
if (_G(charextra)[chaa].xwas != INVALID_X) {
charp->x = _G(charextra)[chaa].xwas;
charp->y = _G(charextra)[chaa].ywas;
_G(charextra)[chaa].xwas = INVALID_X;
}
if ((charp->walking > 0) && (charp->walking < TURNING_AROUND)) {
// if it's not a MoveCharDirect, make sure they end up on a walkable area
@ -922,7 +899,7 @@ void Character_StopMoving(CharacterInfo *charp) {
charp->idleleft = charp->idletime;
// restart the idle animation straight away
charextra[chaa].process_idle_this_time = 1;
_G(charextra)[chaa].process_idle_this_time = 1;
}
if (charp->walking) {
// If the character is currently moving, stop them and reset their frame
@ -941,11 +918,11 @@ void Character_Tint(CharacterInfo *chaa, int red, int green, int blue, int opaci
debug_script_log("Set %s tint RGB(%d,%d,%d) %d%%", chaa->scrname, red, green, blue, opacity);
charextra[chaa->index_id].tint_r = red;
charextra[chaa->index_id].tint_g = green;
charextra[chaa->index_id].tint_b = blue;
charextra[chaa->index_id].tint_level = opacity;
charextra[chaa->index_id].tint_light = (luminance * 25) / 10;
_G(charextra)[chaa->index_id].tint_r = red;
_G(charextra)[chaa->index_id].tint_g = green;
_G(charextra)[chaa->index_id].tint_b = blue;
_G(charextra)[chaa->index_id].tint_level = opacity;
_G(charextra)[chaa->index_id].tint_light = (luminance * 25) / 10;
chaa->flags &= ~CHF_HASLIGHT;
chaa->flags |= CHF_HASTINT;
}
@ -979,7 +956,7 @@ void Character_UnlockViewEx(CharacterInfo *chaa, int stopMoving) {
chaa->pic_xoffs = 0;
chaa->pic_yoffs = 0;
// restart the idle animation straight away
charextra[chaa->index_id].process_idle_this_time = 1;
_G(charextra)[chaa->index_id].process_idle_this_time = 1;
}
@ -1278,7 +1255,7 @@ void Character_SetIgnoreScaling(CharacterInfo *chaa, int yesorno) {
if (yesorno) {
// when setting IgnoreScaling to 1, should reset zoom level
// like it used to in pre-2.71
charextra[chaa->index_id].zoom = 100;
_G(charextra)[chaa->index_id].zoom = 100;
}
Character_SetManualScaling(chaa, yesorno);
}
@ -1412,7 +1389,7 @@ void Character_SetScaleVolume(CharacterInfo *chaa, int yesorno) {
}
int Character_GetScaling(CharacterInfo *chaa) {
return charextra[chaa->index_id].zoom;
return _G(charextra)[chaa->index_id].zoom;
}
void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
@ -1424,7 +1401,7 @@ void Character_SetScaling(CharacterInfo *chaa, int zoomlevel) {
if ((zoomlevel < 5) || (zoomlevel > 200))
quit("!Character.Scaling: scaling level must be between 5 and 200%");
charextra[chaa->index_id].zoom = zoomlevel;
_G(charextra)[chaa->index_id].zoom = zoomlevel;
}
int Character_GetSolid(CharacterInfo *chaa) {
@ -1485,11 +1462,11 @@ void Character_SetSpeechView(CharacterInfo *chaa, int vii) {
}
bool Character_GetThinking(CharacterInfo *chaa) {
return char_thinking == chaa->index_id;
return _G(char_thinking) == chaa->index_id;
}
int Character_GetThinkingFrame(CharacterInfo *chaa) {
if (char_thinking == chaa->index_id)
if (_G(char_thinking) == chaa->index_id)
return chaa->thinkview > 0 ? chaa->frame : -1;
debug_script_warn("Character.ThinkingFrame: character is not currently thinking");
@ -1574,16 +1551,14 @@ void Character_SetZ(CharacterInfo *chaa, int newval) {
chaa->z = newval;
}
extern int char_speaking;
int Character_GetSpeakingFrame(CharacterInfo *chaa) {
if ((face_talking >= 0) && (facetalkrepeat)) {
if (facetalkchar->index_id == chaa->index_id) {
return facetalkframe;
if ((_G(face_talking) >= 0) && (_G(facetalkrepeat))) {
if (_G(facetalkchar)->index_id == chaa->index_id) {
return _G(facetalkframe);
}
} else if (char_speaking >= 0) {
if (char_speaking == chaa->index_id) {
} else if (_G(char_speaking) >= 0) {
if (_G(char_speaking) == chaa->index_id) {
return chaa->frame;
}
}
@ -1631,7 +1606,7 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
// if they are currently walking, save the current Wait
if (chin->walking) {
waitWas = chin->walkwait;
animWaitWas = charextra[chac].animwait;
animWaitWas = _G(charextra)[chac].animwait;
}
StopMoving(chac);
@ -1665,7 +1640,7 @@ void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims)
// are already moving
if (autoWalkAnims) {
chin->walkwait = waitWas;
charextra[chac].animwait = animWaitWas;
_G(charextra)[chac].animwait = animWaitWas;
if (_G(mls)[mslot].pos[0] != _G(mls)[mslot].pos[1]) {
fix_player_sprite(&_G(mls)[mslot], chin);
@ -2033,10 +2008,10 @@ int wantMoveNow(CharacterInfo *chi, CharacterExtras *chex) {
void setup_player_character(int charid) {
_GP(game).playercharacter = charid;
playerchar = &_GP(game).chars[charid];
_sc_PlayerCharPtr = ccGetObjectHandleFromAddress((char *)playerchar);
_G(playerchar) = &_GP(game).chars[charid];
_G(sc_PlayerCharPtr) = ccGetObjectHandleFromAddress((char *)_G(playerchar));
if (loaded_game_file_version < kGameVersion_270) {
ccAddExternalDynamicObject("player", playerchar, &_GP(ccDynamicCharacter));
ccAddExternalDynamicObject("player", _G(playerchar), &_GP(ccDynamicCharacter));
}
}
@ -2082,7 +2057,7 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
if (chi->flags & CHF_SCALEVOLUME) {
// adjust the sound volume using the character's zoom level
int zoom_level = charextra[chi->index_id].zoom;
int zoom_level = _G(charextra)[chi->index_id].zoom;
if (zoom_level == 0)
zoom_level = 100;
@ -2125,7 +2100,7 @@ CharacterInfo *GetCharacterAtRoom(int x, int y) {
return &_GP(game).chars[hsnum];
}
extern int char_lowest_yp, obj_lowest_yp;
extern int obj_lowest_yp;
int is_pos_on_character(int xx, int yy) {
int cc, sppic, lowestyp = 0, lowestwas = -1;
@ -2143,8 +2118,8 @@ int is_pos_on_character(int xx, int yy) {
}
sppic = _G(views)[chin->view].loops[chin->loop].frames[chin->frame].pic;
int usewid = charextra[cc].width;
int usehit = charextra[cc].height;
int usewid = _G(charextra)[cc].width;
int usehit = _G(charextra)[cc].height;
if (usewid == 0) usewid = _GP(game).SpriteInfos[sppic].Width;
if (usehit == 0) usehit = _GP(game).SpriteInfos[sppic].Height;
int xxx = chin->x - game_to_data_coord(usewid) / 2;
@ -2163,7 +2138,7 @@ int is_pos_on_character(int xx, int yy) {
lowestyp = use_base;
lowestwas = cc;
}
char_lowest_yp = lowestyp;
_G(char_lowest_yp) = lowestyp;
return lowestwas;
}
@ -2366,8 +2341,8 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
int oldview = -1, oldloop = -1;
int ovr_type = 0;
text_lips_offset = 0;
text_lips_text = texx;
_G(text_lips_offset) = 0;
_G(text_lips_text) = texx;
Bitmap *closeupface = nullptr;
// TODO: we always call _display_at later which may also start voice-over;
@ -2434,7 +2409,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
if (tdyp < 0) {
int sppic = _G(views)[speakingChar->view].loops[speakingChar->loop].frames[0].pic;
int height = (charextra[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : charextra[aschar].height;
int height = (_G(charextra)[aschar].height < 1) ? _GP(game).SpriteInfos[sppic].Height : _G(charextra)[aschar].height;
tdyp = view->RoomToScreen(0, data_to_game_coord(_GP(game).chars[aschar].get_effective_y()) - height).first.Y
- get_fixed_pixel_size(5);
if (isThought) // if it's a thought, lift it a bit further up
@ -2535,19 +2510,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
int ovr_yp = get_fixed_pixel_size(20);
int view_frame_x = 0;
int view_frame_y = 0;
facetalk_qfg4_override_placement_x = false;
facetalk_qfg4_override_placement_y = false;
_G(facetalk_qfg4_override_placement_x) = false;
_G(facetalk_qfg4_override_placement_y) = false;
if (_GP(game).options[OPT_SPEECHTYPE] == 3) {
// QFG4-style whole screen picture
closeupface = BitmapHelper::CreateBitmap(ui_view.GetWidth(), ui_view.GetHeight(), _GP(spriteset)[viptr->loops[0].frames[0].pic]->GetColorDepth());
closeupface->Clear(0);
if (xx < 0 && _GP(play).speech_portrait_placement) {
facetalk_qfg4_override_placement_x = true;
_G(facetalk_qfg4_override_placement_x) = true;
view_frame_x = _GP(play).speech_portrait_x;
}
if (yy < 0 && _GP(play).speech_portrait_placement) {
facetalk_qfg4_override_placement_y = true;
_G(facetalk_qfg4_override_placement_y) = true;
view_frame_y = _GP(play).speech_portrait_y;
} else {
view_frame_y = ui_view.GetHeight() / 2 - _GP(game).SpriteInfos[viptr->loops[0].frames[0].pic].Height / 2;
@ -2620,19 +2595,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
}
if (_GP(game).options[OPT_SPEECHTYPE] == 3)
overlay_x = 0;
face_talking = add_screen_overlay(overlay_x, ovr_yp, ovr_type, closeupface, closeupface_has_alpha);
facetalkframe = 0;
facetalkwait = viptr->loops[0].frames[0].speed + GetCharacterSpeechAnimationDelay(speakingChar);
facetalkloop = 0;
facetalkview = useview;
facetalkrepeat = (isThought) ? 0 : 1;
facetalkBlinkLoop = 0;
facetalkAllowBlink = 1;
_G(face_talking) = add_screen_overlay(overlay_x, ovr_yp, ovr_type, closeupface, closeupface_has_alpha);
_G(facetalkframe) = 0;
_G(facetalkwait) = viptr->loops[0].frames[0].speed + GetCharacterSpeechAnimationDelay(speakingChar);
_G(facetalkloop) = 0;
_G(facetalkview) = useview;
_G(facetalkrepeat) = (isThought) ? 0 : 1;
_G(facetalkBlinkLoop) = 0;
_G(facetalkAllowBlink) = 1;
if ((isThought) && (speakingChar->flags & CHF_NOBLINKANDTHINK))
facetalkAllowBlink = 0;
facetalkchar = &_GP(game).chars[aschar];
if (facetalkchar->blinktimer < 0)
facetalkchar->blinktimer = facetalkchar->blinkinterval;
_G(facetalkAllowBlink) = 0;
_G(facetalkchar) = &_GP(game).chars[aschar];
if (_G(facetalkchar)->blinktimer < 0)
_G(facetalkchar)->blinktimer = _G(facetalkchar)->blinkinterval;
textcol = -textcol;
overlayPositionFixed = true;
} else if (useview >= 0) {
@ -2655,7 +2630,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
speakingChar->loop = 0;
}
facetalkBlinkLoop = speakingChar->loop;
_G(facetalkBlinkLoop) = speakingChar->loop;
if (speakingChar->on && // don't bother checking if character is not visible (also fixes 'Trilby's Notes' legacy game)
((speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
@ -2678,7 +2653,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
tdxp = OVR_AUTOPLACE;
tdyp = aschar;*/
if (!isThought) // set up the lip sync if not thinking
char_speaking = aschar;
_G(char_speaking) = aschar;
}
} else
@ -2693,7 +2668,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
allowShrink = 0;
if (isThought)
char_thinking = aschar;
_G(char_thinking) = aschar;
_G(our_eip) = 155;
_display_at(tdxp, tdyp, bwidth, texx, DISPLAYTEXT_SPEECH, textcol, isThought, allowShrink, overlayPositionFixed);
@ -2703,8 +2678,8 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
if (closeupface != nullptr)
remove_screen_overlay(ovr_type);
mark_screen_dirty();
face_talking = -1;
facetalkchar = nullptr;
_G(face_talking) = -1;
_G(facetalkchar) = nullptr;
_G(our_eip) = 157;
if (oldview >= 0) {
speakingChar->flags &= ~CHF_FIXVIEW;
@ -2721,19 +2696,19 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
speakingChar->wait = 0;
speakingChar->idleleft = speakingChar->idletime;
// restart the idle animation straight away
charextra[aschar].process_idle_this_time = 1;
_G(charextra)[aschar].process_idle_this_time = 1;
}
char_speaking = -1;
char_thinking = -1;
_G(char_speaking) = -1;
_G(char_thinking) = -1;
if (_GP(play).IsBlockingVoiceSpeech())
stop_voice_speech();
}
int get_character_currently_talking() {
if ((face_talking >= 0) && (facetalkrepeat))
return facetalkchar->index_id;
else if (char_speaking >= 0)
return char_speaking;
if ((_G(face_talking) >= 0) && (_G(facetalkrepeat)))
return _G(facetalkchar)->index_id;
else if (_G(char_speaking) >= 0)
return _G(char_speaking);
return -1;
}
@ -2779,22 +2754,22 @@ int update_lip_sync(int talkview, int talkloop, int *talkframeptr) {
int talkwait = 0;
// lip-sync speech
const char *nowsaying = &text_lips_text[text_lips_offset];
const char *nowsaying = &_G(text_lips_text)[_G(text_lips_offset)];
// if it's an apostraphe, skip it (we'll, I'll, etc)
if (nowsaying[0] == '\'') {
text_lips_offset++;
_G(text_lips_offset)++;
nowsaying++;
}
if (text_lips_offset >= (int)strlen(text_lips_text))
if (_G(text_lips_offset) >= (int)strlen(_G(text_lips_text)))
talkframe = 0;
else {
talkframe = GetLipSyncFrame(nowsaying, &text_lips_offset);
talkframe = GetLipSyncFrame(nowsaying, &_G(text_lips_offset));
if (talkframe >= _G(views)[talkview].loops[talkloop].numFrames)
talkframe = 0;
}
talkwait = loops_per_character + _G(views)[talkview].loops[talkloop].frames[talkframe].speed;
talkwait = _G(loops_per_character) + _G(views)[talkview].loops[talkloop].frames[talkframe].speed;
talkframeptr[0] = talkframe;
return talkwait;
@ -2802,7 +2777,7 @@ int update_lip_sync(int talkview, int talkloop, int *talkframeptr) {
Rect GetCharacterRoomBBox(int charid, bool use_frame_0) {
int width, height;
const CharacterExtras &chex = charextra[charid];
const CharacterExtras &chex = _G(charextra)[charid];
const CharacterInfo &chin = _GP(game).chars[charid];
int frame = use_frame_0 ? 0 : chin.frame;
int pic = _G(views)[chin.view].loops[chin.loop].frames[frame].pic;

View File

@ -219,11 +219,6 @@ Rect GetCharacterRoomBBox(int charid, bool use_frame_0 = false);
// or the one that is least far away from its camera; calculated as a perpendicular distance between two AABBs.
PViewport FindNearestViewport(int charid);
extern CharacterInfo *playerchar;
extern CharacterExtras *charextra;
extern int32_t _sc_PlayerCharPtr;
// order of loops to turn character in circle from down to down
extern int turnlooporder[8];

View File

@ -41,12 +41,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern int char_speaking;
extern unsigned int loopcounter;
#define Random __Rand
@ -268,7 +262,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
doing_nothing = 1;
if (wait > 0) wait--;
else if ((char_speaking == aa) && (_GP(game).options[OPT_LIPSYNCTEXT] != 0)) {
else if ((_G(char_speaking) == aa) && (_GP(game).options[OPT_LIPSYNCTEXT] != 0)) {
// currently talking with lip-sync speech
int fraa = frame;
wait = update_lip_sync(view, loop, &fraa) - 1;
@ -312,7 +306,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
} else
frame++;
if ((aa == char_speaking) &&
if ((aa == _G(char_speaking)) &&
(_GP(play).speech_in_post_state ||
((!_GP(play).speech_has_voice) &&
(_GP(play).close_mouth_speech_time > 0) &&

View File

@ -70,8 +70,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern CharacterInfo *playerchar;
extern int cur_mode, cur_cursor;
extern IGraphicsDriver *gfxDriver;
@ -332,7 +330,7 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
text_color = ds->GetCompatibleColor(_GP(play).read_dialog_option_colour);
} else {
// 'unread' colour
text_color = ds->GetCompatibleColor(playerchar->talkcolor);
text_color = ds->GetCompatibleColor(_G(playerchar)->talkcolor);
}
if (mouseison == ww) {
@ -757,7 +755,7 @@ void DialogOptions::Redraw() {
// Set up the text box, if present
parserInput->Y = curyp + data_to_game_coord(_GP(game).options[OPT_DIALOGGAP]);
parserInput->Width = areawid - get_fixed_pixel_size(10);
parserInput->TextColor = playerchar->talkcolor;
parserInput->TextColor = _G(playerchar)->talkcolor;
if (mouseison == DLG_OPTION_PARSER)
parserInput->TextColor = forecol;

View File

@ -60,16 +60,10 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Shared::BitmapHelper;
extern int longestline;
extern int loops_per_character;
int display_message_aschar = 0;
TopBarSettings topBar;
struct DisplayVars {
int lineheight; // font's height of single line
@ -427,7 +421,7 @@ int GetTextDisplayTime(const char *text, int canberel) {
// This is calculated using a hard-coded 15 for the text speed,
// so that it's always the same no matter how fast the user
// can read.
loops_per_character = (((uselen / _GP(play).lipsync_speed) + 1) * fpstimer) / uselen;
_G(loops_per_character) = (((uselen / _GP(play).lipsync_speed) + 1) * fpstimer) / uselen;
int textDisplayTimeInMS = ((uselen / (_GP(play).text_speed + _GP(play).text_speed_modifier)) + 1) * 1000;
if (textDisplayTimeInMS < _GP(play).text_min_display_time_ms)

View File

@ -100,9 +100,6 @@ extern IDriverDependantBitmap *walkBehindBitmap[MAX_WALK_BEHINDS];
extern int walkBehindsCachedForBgNum;
extern WalkBehindMethodEnum walkBehindMethod;
extern int walk_behind_baselines_changed;
extern CharacterExtras *charextra;
extern CharacterInfo *playerchar;
extern int cur_mode, cur_cursor;
extern int mouse_frame, mouse_delay;
extern int lastmx, lastmy;
@ -1599,29 +1596,29 @@ void prepare_characters_for_drawing() {
// calculate the zoom level
if (chin->flags & CHF_MANUALSCALING) // character ignores scaling
zoom_level = charextra[aa].zoom;
zoom_level = _G(charextra)[aa].zoom;
else if ((onarea <= 0) && (_GP(thisroom).WalkAreas[0].ScalingFar == 0)) {
zoom_level = charextra[aa].zoom;
zoom_level = _G(charextra)[aa].zoom;
// NOTE: room objects don't have this fix
if (zoom_level == 0)
zoom_level = 100;
} else
zoom_level = get_area_scaling(onarea, chin->x, chin->y);
charextra[aa].zoom = zoom_level;
_G(charextra)[aa].zoom = zoom_level;
tint_red = tint_green = tint_blue = tint_amount = tint_light = light_level = 0;
if (chin->flags & CHF_HASTINT) {
// object specific tint, use it
tint_red = charextra[aa].tint_r;
tint_green = charextra[aa].tint_g;
tint_blue = charextra[aa].tint_b;
tint_amount = charextra[aa].tint_level;
tint_light = charextra[aa].tint_light;
tint_red = _G(charextra)[aa].tint_r;
tint_green = _G(charextra)[aa].tint_g;
tint_blue = _G(charextra)[aa].tint_b;
tint_amount = _G(charextra)[aa].tint_level;
tint_light = _G(charextra)[aa].tint_light;
light_level = 0;
} else if (chin->flags & CHF_HASLIGHT) {
light_level = charextra[aa].tint_light;
light_level = _G(charextra)[aa].tint_light;
} else {
get_local_tint(chin->x, chin->y, chin->flags & CHF_NOLIGHTING,
&tint_amount, &tint_red, &tint_green, &tint_blue,
@ -1675,13 +1672,13 @@ void prepare_characters_for_drawing() {
// it needs to be stretched, so calculate the new dimensions
scale_sprite_size(sppic, zoom_level, &newwidth, &newheight);
charextra[aa].width = newwidth;
charextra[aa].height = newheight;
_G(charextra)[aa].width = newwidth;
_G(charextra)[aa].height = newheight;
} else {
// draw at original size, so just use the sprite width and height
// TODO: store width and height always, that's much simplier to use for reference!
charextra[aa].width = 0;
charextra[aa].height = 0;
_G(charextra)[aa].width = 0;
_G(charextra)[aa].height = 0;
newwidth = _GP(game).SpriteInfos[sppic].Width;
newheight = _GP(game).SpriteInfos[sppic].Height;
}
@ -1757,7 +1754,7 @@ void prepare_characters_for_drawing() {
usebasel += _GP(thisroom).Height;
}
} else if (walkBehindMethod == DrawAsSeparateCharSprite) {
sort_out_char_sprite_walk_behind(useindx, bgX, bgY, usebasel, charextra[aa].zoom, newwidth, newheight);
sort_out_char_sprite_walk_behind(useindx, bgX, bgY, usebasel, _G(charextra)[aa].zoom, newwidth, newheight);
} else if (walkBehindMethod == DrawOverCharSprite) {
sort_out_walk_behinds(actsps[useindx], bgX, bgY, usebasel);
}
@ -1946,12 +1943,12 @@ void draw_gui_and_overlays() {
if (((_G(debug_flags) & DBG_NOIFACE) == 0) && (_G(displayed_room) >= 0)) {
int aa;
if (playerchar->activeinv >= MAX_INV) {
if (_G(playerchar)->activeinv >= MAX_INV) {
quit("!The player.activeinv variable has been corrupted, probably as a result\n"
"of an incorrect assignment in the game script.");
}
if (playerchar->activeinv < 1) gui_inv_pic = -1;
else gui_inv_pic = _GP(game).invinfo[playerchar->activeinv].pic;
if (_G(playerchar)->activeinv < 1) gui_inv_pic = -1;
else gui_inv_pic = _GP(game).invinfo[_G(playerchar)->activeinv].pic;
_G(our_eip) = 37;
if (guis_need_update) {
guis_need_update = 0;

View File

@ -110,17 +110,13 @@ using namespace AGS::Shared;
using namespace AGS::Engine;
extern int cur_mode, cur_cursor;
extern SpeechLipSyncLine *splipsync;
extern int numLipLines, curLipLine, curLipLinePhoneme;
extern CharacterExtras *charextra;
extern DialogTopic *dialog;
#if AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
extern int _G(psp_gfx_renderer);
#endif
extern int obj_lowest_yp, char_lowest_yp;
extern int obj_lowest_yp;
extern int actSpsCount;
extern Bitmap **actsps;
@ -465,7 +461,7 @@ void unload_game_file() {
_GP(play).FreeViewportsAndCameras();
_GP(characterScriptObjNames).clear();
free(charextra);
free(_G(charextra));
free(_G(mls));
free(actsps);
free(actspsbmp);
@ -517,15 +513,15 @@ void unload_game_file() {
free(_G(charcache));
_G(charcache) = nullptr;
if (splipsync != nullptr) {
for (int i = 0; i < numLipLines; ++i) {
free(splipsync[i].endtimeoffs);
free(splipsync[i].frame);
if (_G(splipsync) != nullptr) {
for (int i = 0; i < _G(numLipLines); ++i) {
free(_G(splipsync)[i].endtimeoffs);
free(_G(splipsync)[i].frame);
}
free(splipsync);
splipsync = nullptr;
numLipLines = 0;
curLipLine = -1;
free(_G(splipsync));
_G(splipsync) = nullptr;
_G(numLipLines) = 0;
_G(curLipLine) = -1;
}
for (int i = 0; i < _GP(game).numdialog; ++i) {
@ -1146,7 +1142,7 @@ void ReadGameSetupStructBase_Aligned(Stream *in) {
void ReadCharacterExtras_Aligned(Stream *in) {
AlignedStream align_s(in, Shared::kAligned_Read);
for (int i = 0; i < _GP(game).numcharacters; ++i) {
charextra[i].ReadFromFile(&align_s);
_G(charextra)[i].ReadFromFile(&align_s);
align_s.Reset();
}
}
@ -1667,14 +1663,14 @@ int __GetLocationType(int xxx, int yyy, int allowHotspot0) {
wbat = 0;
if ((charat >= 0) && (objat >= 0)) {
if ((wbat > obj_lowest_yp) && (wbat > char_lowest_yp))
if ((wbat > obj_lowest_yp) && (wbat > _G(char_lowest_yp)))
winner = LOCTYPE_HOTSPOT;
else if (obj_lowest_yp > char_lowest_yp)
else if (obj_lowest_yp > _G(char_lowest_yp))
winner = LOCTYPE_OBJ;
else
winner = LOCTYPE_CHAR;
} else if (charat >= 0) {
if (wbat > char_lowest_yp)
if (wbat > _G(char_lowest_yp))
winner = LOCTYPE_HOTSPOT;
else
winner = LOCTYPE_CHAR;
@ -1803,7 +1799,7 @@ void replace_tokens(const char *srcmes, char *destm, int maxlen) {
if (tokentype == 1) {
if ((inx < 1) | (inx >= _GP(game).numinvitems))
quit("!Display: invalid inv item specified in @IN@");
snprintf(tval, sizeof(tval), "%d", playerchar->inv[inx]);
snprintf(tval, sizeof(tval), "%d", _G(playerchar)->inv[inx]);
} else {
if ((inx < 0) | (inx >= MAXGSVALUES))
quit("!Display: invalid global int index speicifed in @GI@");

View File

@ -45,10 +45,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterInfo *playerchar;
GameState::GameState() {
Common::fill(&globalvars[0], &globalvars[MAXGLOBALVARS], 0);
Common::fill(&reserved[0], &reserved[GAME_STATE_RESERVED_INTS], 0);
@ -183,8 +179,8 @@ void GameState::UpdateRoomCamera(int index) {
if ((real_room_sz.Width > rc.GetWidth()) || (real_room_sz.Height > rc.GetHeight())) {
// TODO: split out into Camera Behavior
if (!cam->IsLocked()) {
int x = data_to_game_coord(playerchar->x) - rc.GetWidth() / 2;
int y = data_to_game_coord(playerchar->y) - rc.GetHeight() / 2;
int x = data_to_game_coord(_G(playerchar)->x) - rc.GetWidth() / 2;
int y = data_to_game_coord(_G(playerchar)->y) - rc.GetHeight() / 2;
cam->SetAt(x, y);
}
} else {

View File

@ -41,9 +41,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern SpeechLipSyncLine *splipsync;
extern int numLipLines, curLipLine, curLipLinePhoneme;
void StopAmbientSound(int channel) {
if ((channel < 0) || (channel >= MAX_SOUND_CHANNELS))
quit("!StopAmbientSound: invalid channel");
@ -602,17 +599,17 @@ bool play_voice_speech(int charid, int sndid) {
return false;
int ii; // Compare the base file name to the .pam file name
curLipLine = -1; // See if we have voice lip sync for this line
curLipLinePhoneme = -1;
for (ii = 0; ii < numLipLines; ii++) {
if (ags_stricmp(splipsync[ii].filename, voice_file) == 0) {
curLipLine = ii;
_G(curLipLine) = -1; // See if we have voice lip sync for this line
_G(curLipLinePhoneme) = -1;
for (ii = 0; ii < _G(numLipLines); ii++) {
if (ags_stricmp(_G(splipsync)[ii].filename, voice_file) == 0) {
_G(curLipLine) = ii;
break;
}
}
// if the lip-sync is being used for voice sync, disable
// the text-related lipsync
if (numLipLines > 0)
if (_G(numLipLines) > 0)
_GP(game).options[OPT_LIPSYNCTEXT] = 0;
// change Sierra w/bgrnd to Sierra without background when voice
@ -643,7 +640,7 @@ void stop_voice_speech() {
stop_voice_clip_impl();
// Reset lipsync
curLipLine = -1;
_G(curLipLine) = -1;
// Set back to Sierra w/bgrnd
if (_GP(play).no_textbg_when_voice == 2) {
_GP(play).no_textbg_when_voice = 1;

View File

@ -52,13 +52,6 @@ namespace AGS3 {
using namespace AGS::Shared;
// defined in character unit
extern CharacterExtras *charextra;
extern CharacterInfo *playerchar;
extern int32_t _sc_PlayerCharPtr;
extern CharacterInfo *playerchar;
void StopMoving(int chaa) {
Character_StopMoving(&_GP(game).chars[chaa]);
@ -107,7 +100,7 @@ void SetCharacterIdle(int who, int iview, int itime) {
int GetCharacterWidth(int ww) {
CharacterInfo *char1 = &_GP(game).chars[ww];
if (charextra[ww].width < 1) {
if (_G(charextra)[ww].width < 1) {
if ((char1->view < 0) ||
(char1->loop >= _G(views)[char1->view].numLoops) ||
(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
@ -117,13 +110,13 @@ int GetCharacterWidth(int ww) {
return _GP(game).SpriteInfos[_G(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Width;
} else
return charextra[ww].width;
return _G(charextra)[ww].width;
}
int GetCharacterHeight(int charid) {
CharacterInfo *char1 = &_GP(game).chars[charid];
if (charextra[charid].height < 1) {
if (_G(charextra)[charid].height < 1) {
if ((char1->view < 0) ||
(char1->loop >= _G(views)[char1->view].numLoops) ||
(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
@ -133,7 +126,7 @@ int GetCharacterHeight(int charid) {
return _GP(game).SpriteInfos[_G(views)[char1->view].loops[char1->loop].frames[char1->frame].pic].Height;
} else
return charextra[charid].height;
return _G(charextra)[charid].height;
}
@ -383,7 +376,7 @@ void RunCharacterInteraction(int cc, int mood) {
else if (mood == MODE_TALK) passon = 2;
else if (mood == MODE_USE) {
passon = 3;
cdata = playerchar->activeinv;
cdata = _G(playerchar)->activeinv;
_GP(play).usedinv = cdata;
} else if (mood == MODE_PICKUP) passon = 5;
else if (mood == MODE_CUSTOM1) passon = 6;
@ -452,12 +445,12 @@ void SetActiveInventory(int iit) {
else if (iit != -1)
quitprintf("!SetActiveInventory: invalid inventory number %d", iit);
Character_SetActiveInventory(playerchar, tosend);
Character_SetActiveInventory(_G(playerchar), tosend);
}
void update_invorder() {
for (int cc = 0; cc < _GP(game).numcharacters; cc++) {
charextra[cc].invorder_count = 0;
_G(charextra)[cc].invorder_count = 0;
int ff, howmany;
// Iterate through all inv items, adding them once (or multiple
// times if requested) to the list.
@ -467,16 +460,16 @@ void update_invorder() {
howmany = 1;
for (int ts = 0; ts < howmany; ts++) {
if (charextra[cc].invorder_count >= MAX_INVORDER)
if (_G(charextra)[cc].invorder_count >= MAX_INVORDER)
quit("!Too many inventory items to display: 500 max");
charextra[cc].invorder[charextra[cc].invorder_count] = ff;
charextra[cc].invorder_count++;
_G(charextra)[cc].invorder[_G(charextra)[cc].invorder_count] = ff;
_G(charextra)[cc].invorder_count++;
}
}
}
// backwards compatibility
_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
guis_need_update = 1;
}
@ -485,18 +478,18 @@ void add_inventory(int inum) {
if ((inum < 0) || (inum >= MAX_INV))
quit("!AddInventory: invalid inventory number");
Character_AddInventory(playerchar, &_G(scrInv)[inum], SCR_NO_VALUE);
Character_AddInventory(_G(playerchar), &_G(scrInv)[inum], SCR_NO_VALUE);
_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
}
void lose_inventory(int inum) {
if ((inum < 0) || (inum >= MAX_INV))
quit("!LoseInventory: invalid inventory number");
Character_LoseInventory(playerchar, &_G(scrInv)[inum]);
Character_LoseInventory(_G(playerchar), &_G(scrInv)[inum]);
_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
}
void AddInventoryToCharacter(int charid, int inum) {

View File

@ -53,7 +53,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterInfo *playerchar;
extern int convert_16bit_bgr;
extern IGraphicsDriver *gfxDriver;
extern TreeMap *transtree;
@ -91,7 +90,7 @@ void script_debug(int cmdd, int dataa) {
int rr;
if (cmdd == 0) {
for (rr = 1; rr < _GP(game).numinvitems; rr++)
playerchar->inv[rr] = 1;
_G(playerchar)->inv[rr] = 1;
update_invorder();
// Display("invorder decided there are %d items[display %d",_GP(play).inv_numorder,_GP(play).inv_numdisp);
} else if (cmdd == 1) {
@ -99,7 +98,7 @@ void script_debug(int cmdd, int dataa) {
Display(toDisplay.GetCStr());
// Display("shftR: %d shftG: %d shftB: %d", _G(_rgb_r_shift_16), _G(_rgb_g_shift_16), _G(_rgb_b_shift_16));
// Display("Remaining memory: %d kb",_go32_dpmi_remaining_virtual_memory()/1024);
//Display("Play char bcd: %d",->GetColorDepth(_GP(spriteset)[_G(views)[playerchar->view].frames[playerchar->loop][playerchar->frame].pic]));
//Display("Play char bcd: %d",->GetColorDepth(_GP(spriteset)[_G(views)[_G(playerchar)->view].frames[_G(playerchar)->loop][_G(playerchar)->frame].pic]));
} else if (cmdd == 2) {
// show walkable areas from here
// TODO: support multiple viewports?!

View File

@ -42,8 +42,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern CharacterInfo *playerchar;
void DisableHotspot(int hsnum) {
if ((hsnum < 1) | (hsnum >= MAX_ROOM_HOTSPOTS))
quit("!DisableHotspot: invalid hotspot specified");
@ -104,7 +102,7 @@ void RunHotspotInteraction(int hotspothere, int mood) {
else if (mood == MODE_CUSTOM2) passon = 9;
else if (mood == MODE_USE) {
passon = 3;
cdata = playerchar->activeinv;
cdata = _G(playerchar)->activeinv;
_GP(play).usedinv = cdata;
}

View File

@ -39,8 +39,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern CharacterInfo *playerchar;
void set_inv_item_pic(int invi, int piccy) {
if ((invi < 1) || (invi > _GP(game).numinvitems))
quit("!SetInvItemPic: invalid inventory item specified");
@ -112,7 +110,7 @@ void RunInventoryInteraction(int iit, int modd) {
else if (modd == MODE_HAND)
run_event_block_inv(iit, 1);
else if (modd == MODE_USE) {
_GP(play).usedinv = playerchar->activeinv;
_GP(play).usedinv = _G(playerchar)->activeinv;
run_event_block_inv(iit, 3);
} else if (modd == MODE_TALK)
run_event_block_inv(iit, 2);

View File

@ -52,8 +52,6 @@ using namespace AGS::Shared;
#define OVERLAPPING_OBJECT 1000
extern CharacterInfo *playerchar;
extern int actSpsCount;
extern Bitmap **actsps;
extern IDriverDependantBitmap **actspsbmp;
@ -407,7 +405,7 @@ void RunObjectInteraction(int aa, int mood) {
else if (mood == MODE_CUSTOM2) passon = 7;
else if (mood == MODE_USE) {
passon = 3;
cdata = playerchar->activeinv;
cdata = _G(playerchar)->activeinv;
_GP(play).usedinv = cdata;
}
_G(evblockbasename) = "object%d";

View File

@ -44,7 +44,6 @@ namespace AGS3 {
using namespace Shared;
extern CharacterInfo *playerchar;
extern int in_inv_screen, inv_screen_newroom;
extern int gs_to_newroom;
@ -80,7 +79,7 @@ void NewRoom(int nrnum) {
if (_G(displayed_room) < 0) {
// called from game_start; change the room where the game will start
playerchar->room = nrnum;
_G(playerchar)->room = nrnum;
return;
}
@ -113,16 +112,16 @@ void NewRoom(int nrnum) {
inv_screen_newroom = nrnum;
return;
} else if ((_G(inside_script) == 0) & (_G(in_graph_script) == 0)) {
new_room(nrnum, playerchar);
new_room(nrnum, _G(playerchar));
return;
} else if (_G(inside_script)) {
_G(curscript)->queue_action(ePSANewRoom, nrnum, "NewRoom");
// we might be within a MoveCharacterBlocking -- the room
// change should abort it
if ((playerchar->walking > 0) && (playerchar->walking < TURNING_AROUND)) {
if ((_G(playerchar)->walking > 0) && (_G(playerchar)->walking < TURNING_AROUND)) {
// nasty hack - make sure it doesn't move the character
// to a walkable area
_G(mls)[playerchar->walking].direct = 1;
_G(mls)[_G(playerchar)->walking].direct = 1;
StopMoving(_GP(game).playercharacter);
}
} else if (_G(in_graph_script))
@ -131,7 +130,7 @@ void NewRoom(int nrnum) {
void NewRoomEx(int nrnum, int newx, int newy) {
Character_ChangeRoom(playerchar, nrnum, newx, newy);
Character_ChangeRoom(_G(playerchar), nrnum, newx, newy);
}
void NewRoomNPC(int charid, int nrnum, int newx, int newy) {

View File

@ -34,9 +34,6 @@ namespace AGS3 {
extern int gui_disabled_style;
extern CharacterExtras *charextra;
namespace AGS {
namespace Shared {
@ -55,7 +52,7 @@ void GUIInvWindow::Draw(Bitmap *ds) {
// backwards compatibility
_GP(play).inv_numinline = ColCount;
_GP(play).inv_numdisp = RowCount * ColCount;
_GP(play).obsolete_inv_numorder = charextra[_GP(game).playercharacter].invorder_count;
_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
// if the user changes top_inv_item, switch into backwards
// compatibiltiy mode
if (_GP(play).inv_top)
@ -68,12 +65,12 @@ void GUIInvWindow::Draw(Bitmap *ds) {
int at_x = X;
int at_y = Y;
int lastItem = TopItem + (ColCount * RowCount);
if (lastItem > charextra[GetCharacterId()].invorder_count)
lastItem = charextra[GetCharacterId()].invorder_count;
if (lastItem > _G(charextra)[GetCharacterId()].invorder_count)
lastItem = _G(charextra)[GetCharacterId()].invorder_count;
for (int item = TopItem; item < lastItem; ++item) {
// draw inv graphic
draw_gui_sprite(ds, _GP(game).invinfo[charextra[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
draw_gui_sprite(ds, _GP(game).invinfo[_G(charextra)[GetCharacterId()].invorder[item]].pic, at_x, at_y, true);
at_x += data_to_game_coord(ItemWidth);
// go to next row when appropriate

View File

@ -41,10 +41,7 @@
namespace AGS3 {
extern int cur_cursor;
extern CharacterInfo *playerchar;
void InventoryItem_SetCursorGraphic(ScriptInvItem *iitem, int newSprite) {
set_inv_item_cursorpic(iitem->id, newSprite);
@ -118,7 +115,7 @@ bool InventoryItem_SetTextProperty(ScriptInvItem *scii, const char *property, co
void set_inv_item_cursorpic(int invItemId, int piccy) {
_GP(game).invinfo[invItemId].cursorPic = piccy;
if ((cur_cursor == MODE_USE) && (playerchar->activeinv == invItemId)) {
if ((cur_cursor == MODE_USE) && (_G(playerchar)->activeinv == invItemId)) {
update_inv_cursor(invItemId);
set_mouse_cursor(cur_cursor);
}

View File

@ -53,9 +53,6 @@ namespace AGS3 {
using namespace AGS::Shared;
extern CharacterExtras *charextra;
extern CharacterInfo *playerchar;
int in_inv_screen = 0, inv_screen_newroom = -1;
// *** INV WINDOW FUNCTIONS
@ -112,7 +109,7 @@ int InvWindow_GetItemsPerRow(GUIInvWindow *guii) {
}
int InvWindow_GetItemCount(GUIInvWindow *guii) {
return charextra[guii->GetCharacterId()].invorder_count;
return _G(charextra)[guii->GetCharacterId()].invorder_count;
}
int InvWindow_GetRowCount(GUIInvWindow *guii) {
@ -120,7 +117,7 @@ int InvWindow_GetRowCount(GUIInvWindow *guii) {
}
void InvWindow_ScrollDown(GUIInvWindow *guii) {
if ((charextra[guii->GetCharacterId()].invorder_count) >
if ((_G(charextra)[guii->GetCharacterId()].invorder_count) >
(guii->TopItem + (guii->ColCount * guii->RowCount))) {
guii->TopItem += guii->ColCount;
guis_need_update = 1;
@ -138,9 +135,9 @@ void InvWindow_ScrollUp(GUIInvWindow *guii) {
}
ScriptInvItem *InvWindow_GetItemAtIndex(GUIInvWindow *guii, int index) {
if ((index < 0) || (index >= charextra[guii->GetCharacterId()].invorder_count))
if ((index < 0) || (index >= _G(charextra)[guii->GetCharacterId()].invorder_count))
return nullptr;
return &_G(scrInv)[charextra[guii->GetCharacterId()].invorder[index]];
return &_G(scrInv)[_G(charextra)[guii->GetCharacterId()].invorder[index]];
}
//=============================================================================
@ -157,10 +154,10 @@ int offset_over_inv(GUIInvWindow *inv) {
return -1;
mover += inv->TopItem;
if ((mover < 0) || (mover >= charextra[inv->GetCharacterId()].invorder_count))
if ((mover < 0) || (mover >= _G(charextra)[inv->GetCharacterId()].invorder_count))
return -1;
return charextra[inv->GetCharacterId()].invorder[mover];
return _G(charextra)[inv->GetCharacterId()].invorder[mover];
}
//
@ -241,9 +238,9 @@ int InventoryScreen::Redraw() {
numitems = 0;
widest = 0;
highest = 0;
if (charextra[_GP(game).playercharacter].invorder_count < 0)
if (_G(charextra)[_GP(game).playercharacter].invorder_count < 0)
update_invorder();
if (charextra[_GP(game).playercharacter].invorder_count == 0) {
if (_G(charextra)[_GP(game).playercharacter].invorder_count == 0) {
DisplayMessage(996);
in_inv_screen--;
return -1;
@ -255,17 +252,17 @@ int InventoryScreen::Redraw() {
return -1;
}
for (int i = 0; i < charextra[_GP(game).playercharacter].invorder_count; ++i) {
if (_GP(game).invinfo[charextra[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
dii[numitems].num = charextra[_GP(game).playercharacter].invorder[i];
dii[numitems].sprnum = _GP(game).invinfo[charextra[_GP(game).playercharacter].invorder[i]].pic;
for (int i = 0; i < _G(charextra)[_GP(game).playercharacter].invorder_count; ++i) {
if (_GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].name[0] != 0) {
dii[numitems].num = _G(charextra)[_GP(game).playercharacter].invorder[i];
dii[numitems].sprnum = _GP(game).invinfo[_G(charextra)[_GP(game).playercharacter].invorder[i]].pic;
int snn = dii[numitems].sprnum;
if (_GP(game).SpriteInfos[snn].Width > widest) widest = _GP(game).SpriteInfos[snn].Width;
if (_GP(game).SpriteInfos[snn].Height > highest) highest = _GP(game).SpriteInfos[snn].Height;
numitems++;
}
}
if (numitems != charextra[_GP(game).playercharacter].invorder_count)
if (numitems != _G(charextra)[_GP(game).playercharacter].invorder_count)
quit("inconsistent inventory calculations");
widest += get_fixed_pixel_size(4);
@ -392,21 +389,21 @@ bool InventoryScreen::Run() {
_GP(play).usedinv = toret;
// set the activeinv so the script can check it
int activeinvwas = playerchar->activeinv;
playerchar->activeinv = toret;
int activeinvwas = _G(playerchar)->activeinv;
_G(playerchar)->activeinv = toret;
//ags_domouse(DOMOUSE_DISABLE);
run_event_block_inv(dii[clickedon].num, 3);
// if the script didn't change it, then put it back
if (playerchar->activeinv == toret)
playerchar->activeinv = activeinvwas;
if (_G(playerchar)->activeinv == toret)
_G(playerchar)->activeinv = activeinvwas;
// in case the script did anything to the screen, redraw it
UpdateGameOnce();
// They used the active item and lost it
if (playerchar->inv[toret] < 1) {
if (_G(playerchar)->inv[toret] < 1) {
cmode = CURS_ARROW;
set_mouse_cursor(cmode);
toret = -1;
@ -508,7 +505,7 @@ int __actual_invscreen() {
int invscreen() {
int selt = __actual_invscreen();
if (selt < 0) return -1;
playerchar->activeinv = selt;
_G(playerchar)->activeinv = selt;
guis_need_update = 1;
set_cursor_mode(MODE_USE);
return selt;

View File

@ -52,11 +52,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterInfo *playerchar;
extern IGraphicsDriver *gfxDriver;
extern void ags_domouse(int str);
@ -237,11 +232,11 @@ void set_cursor_mode(int newmode) {
return;
}
if (newmode == MODE_USE) {
if (playerchar->activeinv == -1) {
if (_G(playerchar)->activeinv == -1) {
find_next_enabled_cursor(0);
return;
}
update_inv_cursor(playerchar->activeinv);
update_inv_cursor(_G(playerchar)->activeinv);
}
cur_mode = newmode;
set_default_cursor();
@ -321,7 +316,7 @@ int IsButtonDown(int which) {
int IsModeEnabled(int which) {
return (which < 0) || (which >= _GP(game).numcursors) ? 0 :
which == MODE_USE ? playerchar->activeinv > 0 :
which == MODE_USE ? _G(playerchar)->activeinv > 0 :
(_GP(game).mcurs[which].flags & MCF_DISABLED) == 0;
}
@ -410,7 +405,7 @@ bool is_standard_cursor_enabled(int curs) {
if ((_GP(game).mcurs[curs].flags & MCF_DISABLED) == 0) {
// inventory cursor, and they have an active item
if (curs == MODE_USE) {
if (playerchar->activeinv > 0)
if (_G(playerchar)->activeinv > 0)
return true;
}
// standard cursor that's not disabled, go with it

View File

@ -47,10 +47,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern int face_talking;
extern CharacterExtras *charextra;
extern IGraphicsDriver *gfxDriver;
void Overlay_Remove(ScriptOverlay *sco) {
@ -171,8 +167,8 @@ void remove_screen_overlay_index(size_t over_idx) {
_GP(screenover).erase(_GP(screenover).begin() + over_idx);
// if an overlay before the sierra-style speech one is removed,
// update the index
if (face_talking >= 0 && (size_t)face_talking > over_idx)
face_talking--;
if (_G(face_talking) >= 0 && (size_t)_G(face_talking) > over_idx)
_G(face_talking)--;
}
void remove_screen_overlay(int type) {
@ -236,7 +232,7 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
auto view = FindNearestViewport(charid);
const int charpic = _G(views)[_GP(game).chars[charid].view].loops[_GP(game).chars[charid].loop].frames[0].pic;
const int height = (charextra[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : charextra[charid].height;
const int height = (_G(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _G(charextra)[charid].height;
Point screenpt = view->RoomToScreen(
data_to_game_coord(_GP(game).chars[charid].x),
data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;

View File

@ -85,9 +85,7 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterExtras *charextra;
extern Bitmap *walkareabackup, *walkable_areas_temp;
extern CharacterInfo *playerchar;
extern unsigned int loopcounter;
extern IDriverDependantBitmap *roomBackgroundBmp;
extern IGraphicsDriver *gfxDriver;
@ -287,7 +285,7 @@ void unload_old_room() {
_G(charcache)[ff].inUse = 0;
}
// ensure that any half-moves (eg. with scaled movement) are stopped
charextra[ff].xwas = INVALID_X;
_G(charextra)[ff].xwas = INVALID_X;
}
_GP(play).swap_portrait_lastchar = -1;
@ -422,7 +420,7 @@ static void update_all_viewcams_with_newroom() {
}
}
// forchar = playerchar on NewRoom, or NULL if restore saved game
// forchar = _G(playerchar) on NewRoom, or NULL if restore saved game
void load_new_room(int newnum, CharacterInfo *forchar) {
debug_script_log("Loading room %d", newnum);
@ -911,11 +909,11 @@ void new_room(int newnum, CharacterInfo *forchar) {
newnum = _G(in_leaves_screen);
_G(in_leaves_screen) = -1;
if ((playerchar->following >= 0) &&
(_GP(game).chars[playerchar->following].room != newnum)) {
if ((_G(playerchar)->following >= 0) &&
(_GP(game).chars[_G(playerchar)->following].room != newnum)) {
// the player character is following another character,
// who is not in the new room. therefore, abort the follow
playerchar->following = -1;
_G(playerchar)->following = -1;
}
update_polled_stuff_if_runtime();

View File

@ -256,7 +256,7 @@ HError InitAndRegisterGameEntities() {
setup_player_character(_GP(game).playercharacter);
if (loaded_game_file_version >= kGameVersion_270)
ccAddExternalStaticObject("player", &_sc_PlayerCharPtr, &GlobalStaticManager);
ccAddExternalStaticObject("player", &_G(sc_PlayerCharPtr), &GlobalStaticManager);
return HError::None();
}
@ -331,7 +331,7 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
//
// 3. Allocate and init game objects
//
charextra = (CharacterExtras *)calloc(_GP(game).numcharacters, sizeof(CharacterExtras));
_G(charextra) = (CharacterExtras *)calloc(_GP(game).numcharacters, sizeof(CharacterExtras));
_G(charcache) = (CharacterCache *)calloc(1, sizeof(CharacterCache) * _GP(game).numcharacters + 5);
_G(mls) = (MoveList *)calloc(_GP(game).numcharacters + MAX_ROOM_OBJECTS + 1, sizeof(MoveList));
actSpsCount = _GP(game).numcharacters + MAX_ROOM_OBJECTS + 2;

View File

@ -504,7 +504,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
set_cursor_mode(r_data.CursorMode);
set_mouse_cursor(r_data.CursorID);
if (r_data.CursorMode == MODE_USE)
SetActiveInventory(playerchar->activeinv);
SetActiveInventory(_G(playerchar)->activeinv);
// ensure that the current cursor is locked
_GP(spriteset).Precache(_GP(game).mcurs[r_data.CursorID].pic);
@ -617,8 +617,8 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
if (_G(displayed_room) < 0) {
// the restart point, no room was loaded
load_new_room(playerchar->room, playerchar);
playerchar->prevroom = -1;
load_new_room(_G(playerchar)->room, _G(playerchar));
_G(playerchar)->prevroom = -1;
first_room_initialization();
}

View File

@ -480,7 +480,7 @@ HSaveError WriteCharacters(PStream out) {
out->WriteInt32(_GP(game).numcharacters);
for (int i = 0; i < _GP(game).numcharacters; ++i) {
_GP(game).chars[i].WriteToFile(out.get());
charextra[i].WriteToFile(out.get());
_G(charextra)[i].WriteToFile(out.get());
Properties::WriteValues(_GP(play).charProps[i], out.get());
if (loaded_game_file_version <= kGameVersion_272)
WriteTimesRun272(*_GP(game).intrChar[i], out.get());
@ -496,7 +496,7 @@ HSaveError ReadCharacters(PStream in, int32_t cmp_ver, const PreservedParams &pp
return err;
for (int i = 0; i < _GP(game).numcharacters; ++i) {
_GP(game).chars[i].ReadFromFile(in.get());
charextra[i].ReadFromFile(in.get());
_G(charextra)[i].ReadFromFile(in.get());
Properties::ReadValues(_GP(play).charProps[i], in.get());
if (loaded_game_file_version <= kGameVersion_272)
ReadTimesRun272(*_GP(game).intrChar[i], in.get());

View File

@ -85,14 +85,10 @@ using namespace AGS::Engine;
extern char check_dynamic_sprites_at_exit;
extern char pexbuf[STD_BUFFER_SIZE];
extern SpeechLipSyncLine *splipsync;
extern int numLipLines, curLipLine, curLipLinePhoneme;
extern IGraphicsDriver *gfxDriver;
extern Bitmap **actsps;
extern color palette[256];
extern CharacterExtras *charextra;
extern CharacterInfo *playerchar;
extern Bitmap **guibg;
extern IDriverDependantBitmap **guibgbmp;
@ -319,15 +315,15 @@ void engine_locate_speech_pak() {
if (lipsync_fmt != 4) {
Debug::Printf(kDbgMsg_Info, "Unknown speech lip sync format (%d).\nLip sync disabled.", lipsync_fmt);
} else {
numLipLines = speechsync->ReadInt32();
splipsync = (SpeechLipSyncLine *)malloc(sizeof(SpeechLipSyncLine) * numLipLines);
for (int ee = 0; ee < numLipLines; ee++) {
splipsync[ee].numPhonemes = speechsync->ReadInt16();
speechsync->Read(splipsync[ee].filename, 14);
splipsync[ee].endtimeoffs = (int32_t *)malloc(splipsync[ee].numPhonemes * sizeof(int32_t));
speechsync->ReadArrayOfInt32(splipsync[ee].endtimeoffs, splipsync[ee].numPhonemes);
splipsync[ee].frame = (short *)malloc(splipsync[ee].numPhonemes * sizeof(short));
speechsync->ReadArrayOfInt16(splipsync[ee].frame, splipsync[ee].numPhonemes);
_G(numLipLines) = speechsync->ReadInt32();
_G(splipsync) = (SpeechLipSyncLine *)malloc(sizeof(SpeechLipSyncLine) * _G(numLipLines));
for (int ee = 0; ee < _G(numLipLines); ee++) {
_G(splipsync)[ee].numPhonemes = speechsync->ReadInt16();
speechsync->Read(_G(splipsync)[ee].filename, 14);
_G(splipsync)[ee].endtimeoffs = (int32_t *)malloc(_G(splipsync)[ee].numPhonemes * sizeof(int32_t));
speechsync->ReadArrayOfInt32(_G(splipsync)[ee].endtimeoffs, _G(splipsync)[ee].numPhonemes);
_G(splipsync)[ee].frame = (short *)malloc(_G(splipsync)[ee].numPhonemes * sizeof(short));
speechsync->ReadArrayOfInt16(_G(splipsync)[ee].frame, _G(splipsync)[ee].numPhonemes);
}
}
delete speechsync;
@ -643,8 +639,8 @@ void engine_init_game_settings() {
precache_view(_GP(game).mcurs[ee].view);
}
// may as well preload the character gfx
if (playerchar->view >= 0)
precache_view(playerchar->view);
if (_G(playerchar)->view >= 0)
precache_view(_G(playerchar)->view);
for (ee = 0; ee < MAX_ROOM_OBJECTS; ee++)
_G(objcache)[ee].image = nullptr;
@ -674,8 +670,8 @@ void engine_init_game_settings() {
_GP(game).chars[ee].baseline = -1;
_GP(game).chars[ee].walkwaitcounter = 0;
_GP(game).chars[ee].z = 0;
charextra[ee].xwas = INVALID_X;
charextra[ee].zoom = 100;
_G(charextra)[ee].xwas = INVALID_X;
_G(charextra)[ee].zoom = 100;
if (_GP(game).chars[ee].view >= 0) {
// set initial loop to 0
_GP(game).chars[ee].loop = 0;
@ -683,10 +679,10 @@ void engine_init_game_settings() {
if (_G(views)[_GP(game).chars[ee].view].loops[0].numFrames < 1)
_GP(game).chars[ee].loop = 1;
}
charextra[ee].process_idle_this_time = 0;
charextra[ee].invorder_count = 0;
charextra[ee].slow_move_counter = 0;
charextra[ee].animwait = 0;
_G(charextra)[ee].process_idle_this_time = 0;
_G(charextra)[ee].invorder_count = 0;
_G(charextra)[ee].slow_move_counter = 0;
_G(charextra)[ee].animwait = 0;
}
// multiply up gui positions
guibg = (Bitmap **)malloc(sizeof(Bitmap *) * _GP(game).numgui);
@ -698,8 +694,8 @@ void engine_init_game_settings() {
_G(our_eip) = -5;
for (ee = 0; ee < _GP(game).numinvitems; ee++) {
if (_GP(game).invinfo[ee].flags & IFLG_STARTWITH) playerchar->inv[ee] = 1;
else playerchar->inv[ee] = 0;
if (_GP(game).invinfo[ee].flags & IFLG_STARTWITH) _G(playerchar)->inv[ee] = 1;
else _G(playerchar)->inv[ee] = 0;
}
_GP(play).score = 0;
_GP(play).sierra_inv_color = 7;

View File

@ -75,10 +75,8 @@ using namespace AGS::Shared;
extern int game_paused;
extern int getloctype_index;
extern CharacterInfo *playerchar;
extern int cur_mode;
extern char noWalkBehindsAtAll;
extern CharacterExtras *charextra;
extern int cur_mode, cur_cursor;
@ -146,12 +144,12 @@ static void game_loop_do_late_update() {
static int game_loop_check_ground_level_interactions() {
if ((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0) {
// check if he's standing on a hotspot
int hotspotThere = get_hotspot_at(playerchar->x, playerchar->y);
int hotspotThere = get_hotspot_at(_G(playerchar)->x, _G(playerchar)->y);
// run Stands on Hotspot event
setevent(EV_RUNEVBLOCK, EVB_HOTSPOT, hotspotThere, 0);
// check current region
int onRegion = GetRegionIDAtRoom(playerchar->x, playerchar->y);
int onRegion = GetRegionIDAtRoom(_G(playerchar)->x, _G(playerchar)->y);
int inRoom = _G(displayed_room);
if (onRegion != _GP(play).player_on_region) {
@ -404,8 +402,8 @@ static void check_keyboard_controls() {
int ff;
// MACPORT FIX 9/6/5: added last %s
sprintf(infobuf, "In room %d %s[Player at %d, %d (view %d, loop %d, frame %d)%s%s%s",
_G(displayed_room), (noWalkBehindsAtAll ? "(has no walk-behinds)" : ""), playerchar->x, playerchar->y,
playerchar->view + 1, playerchar->loop, playerchar->frame,
_G(displayed_room), (noWalkBehindsAtAll ? "(has no walk-behinds)" : ""), _G(playerchar)->x, _G(playerchar)->y,
_G(playerchar)->view + 1, _G(playerchar)->loop, _G(playerchar)->frame,
(IsGamePaused() == 0) ? "" : "[Game paused.",
(_GP(play).ground_level_areas_disabled == 0) ? "" : "[Ground areas disabled.",
(IsInterfaceEnabled() == 0) ? "[Game in Wait state" : "");
@ -438,7 +436,7 @@ static void check_keyboard_controls() {
_GP(game).chars[chd].x, _GP(game).chars[chd].y, _GP(game).chars[chd].z,
_GP(game).chars[chd].idleview, _GP(game).chars[chd].idletime, _GP(game).chars[chd].idleleft,
_GP(game).chars[chd].walking, _GP(game).chars[chd].animating, _GP(game).chars[chd].following,
_GP(game).chars[chd].flags, _GP(game).chars[chd].wait, charextra[chd].zoom);
_GP(game).chars[chd].flags, _GP(game).chars[chd].wait, _G(charextra)[chd].zoom);
}
Display(bigbuffer);
@ -540,13 +538,13 @@ static void check_room_edges(int numevents_was) {
if ((_G(numevents) == numevents_was) &&
((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0)) {
if (playerchar->x <= _GP(thisroom).Edges.Left)
if (_G(playerchar)->x <= _GP(thisroom).Edges.Left)
edgesActivated[0] = 1;
else if (playerchar->x >= _GP(thisroom).Edges.Right)
else if (_G(playerchar)->x >= _GP(thisroom).Edges.Right)
edgesActivated[1] = 1;
if (playerchar->y >= _GP(thisroom).Edges.Bottom)
if (_G(playerchar)->y >= _GP(thisroom).Edges.Bottom)
edgesActivated[2] = 1;
else if (playerchar->y <= _GP(thisroom).Edges.Top)
else if (_G(playerchar)->y <= _GP(thisroom).Edges.Top)
edgesActivated[3] = 1;
if ((_GP(play).entered_edge >= 0) && (_GP(play).entered_edge <= 3)) {

View File

@ -52,7 +52,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterInfo *playerchar;
extern int convert_16bit_bgr;
void start_game_init_editor_debugging() {
@ -100,9 +99,9 @@ void start_game() {
if (_G(displayed_room) < 0) {
current_fade_out_effect();
load_new_room(playerchar->room, playerchar);
load_new_room(_G(playerchar)->room, _G(playerchar));
// load_new_room updates it, but it should be -1 in the first room
playerchar->prevroom = -1;
_G(playerchar)->prevroom = -1;
}
first_room_initialization();
@ -131,7 +130,7 @@ void initialize_start_and_play_game(int override_start_room, int loadSaveOnStart
::AGS::g_vm->setRandomNumberSeed(_GP(play).randseed);
if (override_start_room)
playerchar->room = override_start_room;
_G(playerchar)->room = override_start_room;
Debug::Printf(kDbgMsg_Info, "Engine initialization complete");
Debug::Printf(kDbgMsg_Info, "Starting game");

View File

@ -54,15 +54,6 @@ namespace AGS3 {
using namespace AGS::Shared;
using namespace AGS::Engine;
extern CharacterInfo *playerchar;
extern CharacterExtras *charextra;
extern CharacterInfo *facetalkchar;
extern int face_talking, facetalkview, facetalkwait, facetalkframe;
extern int facetalkloop, facetalkrepeat, facetalkAllowBlink;
extern int facetalkBlinkLoop;
extern bool facetalk_qfg4_override_placement_x, facetalk_qfg4_override_placement_y;
extern SpeechLipSyncLine *splipsync;
extern int numLipLines, curLipLine, curLipLinePhoneme;
extern IGraphicsDriver *gfxDriver;
int do_movelist_move(int16_t *mlnum, int32_t *xx, int32_t *yy) {
@ -203,12 +194,12 @@ void update_shadow_areas() {
// shadow areas
int onwalkarea = get_walkable_area_at_character(_GP(game).playercharacter);
if (onwalkarea < 0);
else if (playerchar->flags & CHF_FIXVIEW);
else if (_G(playerchar)->flags & CHF_FIXVIEW);
else {
onwalkarea = _GP(thisroom).WalkAreas[onwalkarea].Light;
if (onwalkarea > 0) playerchar->view = onwalkarea - 1;
else if (_GP(thisroom).Options.PlayerView == 0) playerchar->view = playerchar->defview;
else playerchar->view = _GP(thisroom).Options.PlayerView - 1;
if (onwalkarea > 0) _G(playerchar)->view = onwalkarea - 1;
else if (_GP(thisroom).Options.PlayerView == 0) _G(playerchar)->view = _G(playerchar)->defview;
else _G(playerchar)->view = _GP(thisroom).Options.PlayerView - 1;
}
}
@ -218,7 +209,7 @@ void update_character_move_and_anim(int &numSheep, int *followingAsSheep) {
if (_GP(game).chars[aa].on != 1) continue;
CharacterInfo *chi = &_GP(game).chars[aa];
CharacterExtras *chex = &charextra[aa];
CharacterExtras *chex = &_G(charextra)[aa];
chi->UpdateMoveAndAnim(aa, chex, numSheep, followingAsSheep);
}
@ -293,57 +284,57 @@ void update_sierra_speech() {
auto *ch = lock.GetChannel(SCHAN_SPEECH);
voice_pos_ms = ch ? ch->get_pos_ms() : -1;
}
if ((face_talking >= 0) && (_GP(play).fast_forward == 0)) {
if ((_G(face_talking) >= 0) && (_GP(play).fast_forward == 0)) {
int updatedFrame = 0;
if ((facetalkchar->blinkview > 0) && (facetalkAllowBlink)) {
if (facetalkchar->blinktimer > 0) {
if ((_G(facetalkchar)->blinkview > 0) && (_G(facetalkAllowBlink))) {
if (_G(facetalkchar)->blinktimer > 0) {
// countdown to playing blink anim
facetalkchar->blinktimer--;
if (facetalkchar->blinktimer == 0) {
facetalkchar->blinkframe = 0;
facetalkchar->blinktimer = -1;
_G(facetalkchar)->blinktimer--;
if (_G(facetalkchar)->blinktimer == 0) {
_G(facetalkchar)->blinkframe = 0;
_G(facetalkchar)->blinktimer = -1;
updatedFrame = 2;
}
} else if (facetalkchar->blinktimer < 0) {
} else if (_G(facetalkchar)->blinktimer < 0) {
// currently playing blink anim
if (facetalkchar->blinktimer < ((0 - 6) - _G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].frames[facetalkchar->blinkframe].speed)) {
if (_G(facetalkchar)->blinktimer < ((0 - 6) - _G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].frames[_G(facetalkchar)->blinkframe].speed)) {
// time to advance to next frame
facetalkchar->blinktimer = -1;
facetalkchar->blinkframe++;
_G(facetalkchar)->blinktimer = -1;
_G(facetalkchar)->blinkframe++;
updatedFrame = 2;
if (facetalkchar->blinkframe >= _G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].numFrames) {
facetalkchar->blinkframe = 0;
facetalkchar->blinktimer = facetalkchar->blinkinterval;
if (_G(facetalkchar)->blinkframe >= _G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].numFrames) {
_G(facetalkchar)->blinkframe = 0;
_G(facetalkchar)->blinktimer = _G(facetalkchar)->blinkinterval;
}
} else
facetalkchar->blinktimer--;
_G(facetalkchar)->blinktimer--;
}
}
if (curLipLine >= 0) {
if (_G(curLipLine) >= 0) {
// check voice lip sync
if (curLipLinePhoneme >= splipsync[curLipLine].numPhonemes) {
if (_G(curLipLinePhoneme) >= _G(splipsync)[_G(curLipLine)].numPhonemes) {
// the lip-sync has finished, so just stay idle
} else {
while ((curLipLinePhoneme < splipsync[curLipLine].numPhonemes) &&
((curLipLinePhoneme < 0) || (voice_pos_ms >= splipsync[curLipLine].endtimeoffs[curLipLinePhoneme]))) {
curLipLinePhoneme++;
if (curLipLinePhoneme >= splipsync[curLipLine].numPhonemes)
facetalkframe = _GP(game).default_lipsync_frame;
while ((_G(curLipLinePhoneme) < _G(splipsync)[_G(curLipLine)].numPhonemes) &&
((_G(curLipLinePhoneme) < 0) || (voice_pos_ms >= _G(splipsync)[_G(curLipLine)].endtimeoffs[_G(curLipLinePhoneme)]))) {
_G(curLipLinePhoneme)++;
if (_G(curLipLinePhoneme) >= _G(splipsync)[_G(curLipLine)].numPhonemes)
_G(facetalkframe) = _GP(game).default_lipsync_frame;
else
facetalkframe = splipsync[curLipLine].frame[curLipLinePhoneme];
_G(facetalkframe) = _G(splipsync)[_G(curLipLine)].frame[_G(curLipLinePhoneme)];
if (facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames)
facetalkframe = 0;
if (_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames)
_G(facetalkframe) = 0;
updatedFrame |= 1;
}
}
} else if (facetalkwait > 0) facetalkwait--;
} else if (_G(facetalkwait) > 0) _G(facetalkwait)--;
// don't animate if the speech has finished
else if ((_GP(play).messagetime < 1) && (facetalkframe == 0) &&
else if ((_GP(play).messagetime < 1) && (_G(facetalkframe) == 0) &&
// if _GP(play).close_mouth_speech_time = 0, this means animation should play till
// the speech ends; but this should not work in voice mode, and also if the
// speech is in the "post" state
@ -356,32 +347,32 @@ void update_sierra_speech() {
(!_GP(play).speech_has_voice &&
(_GP(play).messagetime < _GP(play).close_mouth_speech_time) &&
(_GP(play).close_mouth_speech_time > 0))) {
facetalkframe = 0;
facetalkwait = _GP(play).messagetime;
} else if ((_GP(game).options[OPT_LIPSYNCTEXT]) && (facetalkrepeat > 0)) {
_G(facetalkframe) = 0;
_G(facetalkwait) = _GP(play).messagetime;
} else if ((_GP(game).options[OPT_LIPSYNCTEXT]) && (_G(facetalkrepeat) > 0)) {
// lip-sync speech (and not a thought)
facetalkwait = update_lip_sync(facetalkview, facetalkloop, &facetalkframe);
// It is actually displayed for facetalkwait+1 loops
_G(facetalkwait) = update_lip_sync(_G(facetalkview), _G(facetalkloop), &_G(facetalkframe));
// It is actually displayed for _G(facetalkwait)+1 loops
// (because when it's 1, it gets --'d then wait for next time)
facetalkwait--;
_G(facetalkwait)--;
} else {
// normal non-lip-sync
facetalkframe++;
if ((facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames) ||
_G(facetalkframe)++;
if ((_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames) ||
(!_GP(play).speech_has_voice && (_GP(play).messagetime < 1) && (_GP(play).close_mouth_speech_time > 0))) {
if ((facetalkframe >= _G(views)[facetalkview].loops[facetalkloop].numFrames) &&
(_G(views)[facetalkview].loops[facetalkloop].RunNextLoop())) {
facetalkloop++;
if ((_G(facetalkframe) >= _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].numFrames) &&
(_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].RunNextLoop())) {
_G(facetalkloop)++;
} else {
facetalkloop = 0;
_G(facetalkloop) = 0;
}
facetalkframe = 0;
if (!facetalkrepeat)
facetalkwait = 999999;
_G(facetalkframe) = 0;
if (!_G(facetalkrepeat))
_G(facetalkwait) = 999999;
}
if ((facetalkframe != 0) || (facetalkrepeat == 1))
facetalkwait = _G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe].speed + GetCharacterSpeechAnimationDelay(facetalkchar);
if ((_G(facetalkframe) != 0) || (_G(facetalkrepeat) == 1))
_G(facetalkwait) = _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)].speed + GetCharacterSpeechAnimationDelay(_G(facetalkchar));
}
updatedFrame |= 1;
}
@ -390,42 +381,42 @@ void update_sierra_speech() {
if ((updatedFrame) && (_G(is_text_overlay) > 0)) {
if (updatedFrame & 1)
CheckViewFrame(facetalkview, facetalkloop, facetalkframe);
CheckViewFrame(_G(facetalkview), _G(facetalkloop), _G(facetalkframe));
if (updatedFrame & 2)
CheckViewFrame(facetalkchar->blinkview, facetalkBlinkLoop, facetalkchar->blinkframe);
CheckViewFrame(_G(facetalkchar)->blinkview, _G(facetalkBlinkLoop), _G(facetalkchar)->blinkframe);
int thisPic = _G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe].pic;
int thisPic = _G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)].pic;
int view_frame_x = 0;
int view_frame_y = 0;
if (_GP(game).options[OPT_SPEECHTYPE] == 3) {
// QFG4-style fullscreen dialog
if (facetalk_qfg4_override_placement_x) {
if (_G(facetalk_qfg4_override_placement_x)) {
view_frame_x = _GP(play).speech_portrait_x;
}
if (facetalk_qfg4_override_placement_y) {
if (_G(facetalk_qfg4_override_placement_y)) {
view_frame_y = _GP(play).speech_portrait_y;
} else {
view_frame_y = (_GP(screenover)[face_talking].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
view_frame_y = (_GP(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
}
_GP(screenover)[face_talking].pic->Clear(0);
_GP(screenover)[_G(face_talking)].pic->Clear(0);
} else {
_GP(screenover)[face_talking].pic->ClearTransparent();
_GP(screenover)[_G(face_talking)].pic->ClearTransparent();
}
Bitmap *frame_pic = _GP(screenover)[face_talking].pic;
const ViewFrame *face_vf = &_G(views)[facetalkview].loops[facetalkloop].frames[facetalkframe];
Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].pic;
const ViewFrame *face_vf = &_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)];
bool face_has_alpha = (_GP(game).SpriteInfos[face_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
DrawViewFrame(frame_pic, face_vf, view_frame_x, view_frame_y);
if ((facetalkchar->blinkview > 0) && (facetalkchar->blinktimer < 0)) {
ViewFrame *blink_vf = &_G(views)[facetalkchar->blinkview].loops[facetalkBlinkLoop].frames[facetalkchar->blinkframe];
if ((_G(facetalkchar)->blinkview > 0) && (_G(facetalkchar)->blinktimer < 0)) {
ViewFrame *blink_vf = &_G(views)[_G(facetalkchar)->blinkview].loops[_G(facetalkBlinkLoop)].frames[_G(facetalkchar)->blinkframe];
face_has_alpha |= (_GP(game).SpriteInfos[blink_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
// draw the blinking sprite on top
DrawViewFrame(frame_pic, blink_vf, view_frame_x, view_frame_y, face_has_alpha);
}
gfxDriver->UpdateDDBFromBitmap(_GP(screenover)[face_talking].bmp, _GP(screenover)[face_talking].pic, face_has_alpha);
gfxDriver->UpdateDDBFromBitmap(_GP(screenover)[_G(face_talking)].bmp, _GP(screenover)[_G(face_talking)].pic, face_has_alpha);
} // end if updatedFrame
}
}

View File

@ -100,8 +100,6 @@ void set_clip_to_channel(int chanid, SOUNDCLIP *clip) {
}
//-----------------------
extern CharacterInfo *playerchar;
void calculate_reserved_channel_count() {
int reservedChannels = 0;
for (size_t i = 0; i < _GP(game).audioClipTypes.size(); i++) {
@ -513,8 +511,8 @@ SOUNDCLIP *load_sound_clip_from_old_style_number(bool isMusic, int indexNumber,
//=============================================================================
int get_volume_adjusted_for_distance(int volume, int sndX, int sndY, int sndMaxDist) {
int distx = playerchar->x - sndX;
int disty = playerchar->y - sndY;
int distx = _G(playerchar)->x - sndX;
int disty = _G(playerchar)->y - sndY;
// it uses Allegro's "fix" sqrt without the ::
int dist = (int)::sqrt((double)(distx * distx + disty * disty));

View File

@ -56,7 +56,6 @@ namespace AGS3 {
extern int gameHasBeenRestored;
extern unsigned int load_new_game;
extern CharacterInfo *playerchar;
int run_dialog_request(int parmtr) {
_GP(play).stop_dialog_at_end = DIALOG_RUNNING;
@ -494,7 +493,7 @@ void post_script_cleanup() {
case ePSANewRoom:
// only change rooms when all scripts are done
if (_G(num_scripts) == 0) {
new_room(thisData, playerchar);
new_room(thisData, _G(playerchar));
// don't allow any pending room scripts from the old room
// in run_another to be executed
return;
@ -690,7 +689,7 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
SetDialogOption(IPARAM1, IPARAM2, 0);
break;
case 12: // Go To Screen
Character_ChangeRoomAutoPosition(playerchar, IPARAM1, IPARAM2);
Character_ChangeRoomAutoPosition(_G(playerchar), IPARAM1, IPARAM2);
return -1;
case 13: // Add Inventory
add_inventory(IPARAM1);
@ -729,7 +728,7 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
cmdsrun[0] --;
break;
case 21: // if player has inventory item
if (playerchar->inv[IPARAM1] > 0)
if (_G(playerchar)->inv[IPARAM1] > 0)
if (run_interaction_commandlist(nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
return -1;
break;

View File

@ -95,6 +95,8 @@ struct CCInventory;
struct CCObject;
struct CCRegion;
struct CharacterCache;
struct CharacterExtras;
struct CharacterInfo;
struct COLOR_MAP;
struct DirtyRects;
struct ExecutingScript;
@ -126,6 +128,7 @@ struct ScriptRegion;
struct ScriptString;
struct ScriptSystem;
struct SOUNDCLIP;
struct SpeechLipSyncLine;
struct SpriteListEntry;
struct StaticArray;
struct SystemImports;
@ -259,6 +262,34 @@ public:
/**@}*/
/**
* \defgroup character globals
* @{
*/
CharacterExtras *_charextra = nullptr;
CharacterInfo *_playerchar = nullptr;
int32_t _sc_PlayerCharPtr = 0;
int _char_lowest_yp = 0;
// Sierra-style speech settings
int _face_talking = -1, _facetalkview = 0, _facetalkwait = 0, _facetalkframe = 0;
int _facetalkloop = 0, _facetalkrepeat = 0, _facetalkAllowBlink = 1;
int _facetalkBlinkLoop = 0;
CharacterInfo *_facetalkchar = nullptr;
// Do override default portrait position during QFG4-style speech overlay update
bool _facetalk_qfg4_override_placement_x = false;
bool _facetalk_qfg4_override_placement_y = false;
// lip-sync speech settings
int _loops_per_character, _text_lips_offset, _char_speaking = -1;
int _char_thinking = -1;
const char *_text_lips_text = nullptr;
SpeechLipSyncLine *_splipsync = nullptr;
int _numLipLines = 0, _curLipLine = -1, _curLipLinePhoneme = 0;
/**@}*/
/**
* \defgroup debug globals
* @{