2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/script/sndscrpt.cpp,v 1.36 1999/08/05 17:34:28 Justin Exp $
43 // Include this last, please
46 // Our special spew that works in playtest
48 #define sndSpew(x) if (!config_is_defined("ScriptSoundSpew")) ; else mprintf x
53 ///////////////////////////////////////////////////////////////////////////////
55 // Message implementations
58 // We keep track of all sounds started by scripts, and when they end
59 // we use our callback to run the SoundDone or SchemaDone message on
60 // whichever object's script started the sound.
70 #define MAX_TAG_SIZE 128
72 // The handles used by the schema system come directly from appsfx.
73 // So we can depend on them to be unique no matter what calls they
79 mxs_vector m_Coordinates
;
80 ObjID m_CallbackObjID
;
81 ObjID m_TargetObjID
; // the sound was played _on_ this object
82 Label m_Name
; // either the sound name or the schema name
85 // horrifying replay system
86 eSndPlayType m_replay
;
91 char m_envTagsString
[MAX_TAG_SIZE
];
93 cSoundRecord(int iHandle
,
94 mxs_vector
*pCoordinates
,
100 m_Coordinates(*pCoordinates
),
101 m_CallbackObjID(CallbackObjID
),
102 m_TargetObjID(TargetObjID
),
104 m_bIsSchema(bIsSchema
)
113 static BOOL kill_on_load
=FALSE
;
115 // This is used to keep track of both active raw sounds and active
117 static cDynArray
<cSoundRecord
*> g_ActiveSounds
;
119 static LazyAggMember(IObjectSystem
) pObjSys
;
120 static LazyAggMember(IScriptMan
) pScriptMan
;
122 ///////////////////////
125 void ScriptSoundInit(void)
127 if (config_is_defined("sndscrpt_kill_restart"))
131 void ScriptSoundTerm(void)
135 ///////////////////////
138 // these are later in the file, sorry
139 static void ActiveSchemaDoneCallback(int iHandle
, int iSchemaID
, void *pIgnoreUserData
);
140 static void SFXParamsSetup(sfx_parm
*pParams
, int iFlags
, eSoundNetwork net
);
142 static void SchemaParamsSetup(sSchemaCallParams
*pParams
,
144 mxs_vector
*Coordinates
,
148 pParams
->flags
= SCH_SET_CALLBACK
| SCH_FORCE_PLAY
| iFlags
;
149 if (net
== kSoundNetworkAmbient
)
150 pParams
->flags
|= SCH_NETWORK
;
151 else if (net
== kSoundNoNetworkSpatial
)
152 pParams
->flags
|= SCH_NO_NETWORK
;
153 pParams
->sourceID
= SourceObjID
;
154 pParams
->callback
= ActiveSchemaDoneCallback
;
155 pParams
->pSourceLoc
= Coordinates
;
158 static int SndScrptGen(Label
*lname
, int iFlags
, ObjID call
, ObjID targ
, ObjID obj2
,
159 mxs_vector
*crd
, cTagSet
*pTags
, BOOL amb
, eEnvSoundLoc loc
, eSndPlayType play
, eSoundNetwork net
)
161 sSchemaCallParams CallParams
;
162 int iHandle
=SFX_NO_HND
;
169 SFXParamsSetup(&parm
, iFlags
, net
);
171 iHandle
= g_pPropSnd
->GenerateSound(lname
->text
, &parm
);
173 iHandle
= g_pPropSnd
->GenerateSound(targ
, OBJ_NULL
, lname
->text
, 1.0, &parm
, kGSF_ForcePlay
);
176 SchemaParamsSetup(&CallParams
, targ
, crd
, iFlags
, net
);
177 iHandle
= SchemaPlay(lname
, &CallParams
);
180 SchemaParamsSetup(&CallParams
, targ
, crd
, iFlags
, net
);
184 iHandle
= ESndPlayObj(pTags
, targ
, obj2
, &CallParams
);
186 case kEnvSoundAtObjLoc
:
187 iHandle
= ESndPlayLoc(pTags
, targ
, obj2
, crd
, &CallParams
);
189 case kEnvSoundAmbient
:
190 iHandle
= ESndPlay(pTags
, targ
, obj2
, &CallParams
);
198 ///////////////////////
201 #define kSndScriptSaveVer 1
202 static TagFileTag sound_tag
= {"SndScript"};
203 static TagVersion sound_ver
= { kSndScriptSaveVer
, 0 };
205 void ScriptSoundSave(ITagFile
*file
)
206 { // go through and write out the data we need
207 HRESULT result
=file
->OpenBlock(&sound_tag
,&sound_ver
);
211 int cnt
=g_ActiveSounds
.Size();
212 file
->Write((char *)&cnt
,sizeof(int));
213 for (int i
= 0; i
< g_ActiveSounds
.Size(); ++i
)
214 if (file
->Write((char *)g_ActiveSounds
[i
],sizeof(cSoundRecord
))!=sizeof(cSoundRecord
))
217 Warning(("ActiveSounds failed to write\n"));
220 sndSpew(("sndscrpt Saved %d records\n",cnt
));
224 BOOL
SndScriptRestartSavedSounds(cSoundRecord
*sndDat
)
227 cTagSet tmp
; // here comes the HACK HACK HACK
229 sndDat
->m_CallbackObjID
= ObjRemapOnLoad(sndDat
->m_CallbackObjID
);
230 sndDat
->m_TargetObjID
= ObjRemapOnLoad(sndDat
->m_TargetObjID
);
231 if (sndDat
->m_replay
==kPlaySchemaEnv
)
232 { // only used for schemaEnv, so really
233 tmp
.FromString(sndDat
->m_envTagsString
);
234 sndDat
->m_Obj2
= ObjRemapOnLoad(sndDat
->m_Obj2
);
238 SndScrptGen(&sndDat
->m_Name
,sndDat
->m_iFlags
,
239 sndDat
->m_CallbackObjID
,sndDat
->m_TargetObjID
,sndDat
->m_Obj2
,
240 &sndDat
->m_Coordinates
,&tmp
,sndDat
->m_bAmbient
,sndDat
->m_eLoc
,
241 sndDat
->m_replay
,kSoundNetDefault
);
242 if (sndDat
->m_replay
==kPlaySound
)
243 worked
=(hnd
!=SFX_NO_HND
);
245 worked
=(hnd
!=SCH_HANDLE_NULL
);
248 sndDat
->m_iHandle
=hnd
;
249 g_ActiveSounds
.Append(sndDat
);
250 sndSpew(("Restarted %s (callback %s targ %s) type %d\n",sndDat
->m_Name
.text
,
251 ObjWarnName(sndDat
->m_CallbackObjID
),
252 ObjWarnName(sndDat
->m_TargetObjID
),
258 void SndScriptSendSavedMsg(cSoundRecord
*sndDat
)
260 // need to ObjRemap here, i think....
261 sndDat
->m_CallbackObjID
= ObjRemapOnLoad(sndDat
->m_CallbackObjID
);
262 sndDat
->m_TargetObjID
= ObjRemapOnLoad(sndDat
->m_TargetObjID
);
263 sndSpew(("savedispatch call %s targ %s - %s (a %s)\n",
264 ObjWarnName(sndDat
->m_CallbackObjID
),
265 ObjWarnName(sndDat
->m_TargetObjID
),
267 sndDat
->m_bIsSchema
?"Schema":"Sound"
269 if (sndDat
->m_bIsSchema
)
272 = new sSchemaDoneMsg(sndDat
->m_CallbackObjID
,
273 sndDat
->m_TargetObjID
,
274 sndDat
->m_Coordinates
,
275 sndDat
->m_Name
.text
);
276 pScriptMan
->PostMessage(pMsg
);
282 = new sSoundDoneMsg(sndDat
->m_CallbackObjID
,
283 sndDat
->m_TargetObjID
,
284 sndDat
->m_Coordinates
,
285 sndDat
->m_Name
.text
);
286 pScriptMan
->PostMessage(pMsg
);
291 static cDynArray
<cSoundRecord
*> _LoadSounds
;
293 void ScriptSoundLoad(ITagFile
*file
)
294 { // go through and postmessage the kills
295 TagVersion local_ver
=sound_ver
;
296 HRESULT result
=file
->OpenBlock(&sound_tag
,&local_ver
);
302 if (file
->Read((char *)&cnt
,sizeof(int))==sizeof(int))
303 for (int i
= 0; i
< cnt
; ++i
)
305 cSoundRecord
*tmpSoundRec
= new cSoundRecord();
306 if (file
->Read((char *)tmpSoundRec
,sizeof(cSoundRecord
))!=sizeof(cSoundRecord
))
309 Warning(("ActiveSounds failed to read\n"));
314 _LoadSounds
.Append(tmpSoundRec
);
317 Warning(("ActiveSounds couldnt get a count\n"));
320 sndSpew(("sndscrpt loaded %d records\n",cnt
));
323 void ScriptSoundPostLoad(void)
325 for (int i
=0; i
<_LoadSounds
.Size(); i
++)
329 SndScriptSendSavedMsg(_LoadSounds
[i
]);
330 delete _LoadSounds
[i
];
334 if (!SndScriptRestartSavedSounds(_LoadSounds
[i
]))
336 SndScriptSendSavedMsg(_LoadSounds
[i
]);
337 delete _LoadSounds
[i
];
341 _LoadSounds
.SetSize(0);
344 // if the data is real, call postload
345 void ScriptSoundEnterModeHack(void)
347 ScriptSoundPostLoad();
350 void ScriptSoundReset(void)
352 if (g_ActiveSounds
.Size())
355 mprintf("Reseting Script Sounds but there are active sounds - TELL DOUG\n");
360 ///////////////////////
363 // When a scripted schema finishes, we do this.
364 static void ActiveSchemaDoneCallback(int iHandle
, int iSchemaID
,
365 void *pIgnoreUserData
)
367 if (g_ActiveSounds
.Size() == 0)
368 Warning(("No scripted schemas playing in callback; handle is %d\n",
371 sndSpew(("Schema %s is done (handle %d)\n", ObjWarnName(iSchemaID
), iHandle
));
373 for (int i
= 0; i
< g_ActiveSounds
.Size(); ++i
) {
374 if (g_ActiveSounds
[i
]->m_iHandle
== iHandle
) {
376 if (g_ActiveSounds
[i
]->m_bIsSchema
== FALSE
)
377 Warning(("Scripted schema callback found raw schema %d."
378 " Yeah, Whatever.\n", g_ActiveSounds
[i
]->m_iHandle
));
381 sndSpew((" found!\n"));
384 = new sSchemaDoneMsg(g_ActiveSounds
[i
]->m_CallbackObjID
,
385 g_ActiveSounds
[i
]->m_TargetObjID
,
386 g_ActiveSounds
[i
]->m_Coordinates
,
387 g_ActiveSounds
[i
]->m_Name
.text
);
388 pScriptMan
->PostMessage(pMsg
);
391 delete g_ActiveSounds
[i
];
392 g_ActiveSounds
.DeleteItem(i
);
398 sndSpew((" not found!\n"));
400 for (int k
=0; k
<g_ActiveSounds
.Size(); k
++)
401 sndSpew((" %s, handle %d\n", ObjWarnName(g_ActiveSounds
[k
]->m_TargetObjID
), g_ActiveSounds
[k
]->m_iHandle
));
404 Warning(("Scripted schema handle not found in callback: %d\n", iHandle
));
408 static void ActiveSoundDoneCallback(int iHandle
, void *pIgnoreUserData
)
410 if (g_ActiveSounds
.Size() == 0)
411 Warning(("No scripted sounds playing in callback; handle is %d\n",
414 for (int i
= 0; i
< g_ActiveSounds
.Size(); ++i
) {
415 if (g_ActiveSounds
[i
]->m_iHandle
== iHandle
) {
417 if (g_ActiveSounds
[i
]->m_bIsSchema
== TRUE
)
418 Warning(("Scripted raw sound callback found schema %d."
419 " Yeah, Whatever.\n", g_ActiveSounds
[i
]->m_iHandle
));
423 = new sSoundDoneMsg(g_ActiveSounds
[i
]->m_CallbackObjID
,
424 g_ActiveSounds
[i
]->m_TargetObjID
,
425 g_ActiveSounds
[i
]->m_Coordinates
,
426 g_ActiveSounds
[i
]->m_Name
.text
);
427 pScriptMan
->PostMessage(pMsg
);
430 delete g_ActiveSounds
[i
];
431 g_ActiveSounds
.DeleteItem(i
);
437 Warning(("Scripted sound handle not found in callback: %d\n", iHandle
));
441 // This is a lobotomized version of SchemaParamsSetup in schema.cpp.
442 // When we go back and add support for panning, custom fades, etc., we
443 // can pattern it after that.
444 static void SFXParamsSetup(sfx_parm
*pParams
, int iFlags
, eSoundNetwork net
)
446 pParams
->flag
= iFlags
;
447 if (net
== kSoundNetworkAmbient
)
448 pParams
->flag
|= SFXFLG_NET_AMB
;
449 else if (net
== kSoundNoNetworkSpatial
)
450 pParams
->flag
|= SFXFLG_NO_NET
;
452 pParams
->end_callback
= &ActiveSoundDoneCallback
;
453 pParams
->loop_callback
= NULL
;
454 pParams
->user_data
= 0;
461 pParams
->num_loops
= SFX_LOOP_INFINITE
;
465 // This is the stuff held in common by the three sound playing
467 static bool PlayAndRememberSound(const char *SoundName
,
472 eSoundSpecial Special
= kSoundNormal
,
473 eSoundNetwork Network
= kSoundNetDefault
)
476 memcpy(&SoundLabel
.text
, SoundName
, 15);
477 SoundLabel
.text
[15] = 0;
484 iFlags
= SFXFLG_LOOP
;
490 int iHandle
= SndScrptGen(&SoundLabel
,iFlags
,CallObjID
,TargObjID
,OBJ_NULL
,
491 pCoord
,NULL
,bAmbient
,(eEnvSoundLoc
)0,kPlaySound
,
494 if (iHandle
!= SFX_NO_HND
)
496 cSoundRecord
*t
= new cSoundRecord(iHandle
, pCoord
, CallObjID
, TargObjID
, &SoundLabel
, FALSE
);
498 // @REPLAY - needs iFlags, bAmibent
499 t
->m_bAmbient
= bAmbient
;
500 t
->m_iFlags
= iFlags
;
501 t
->m_replay
= kPlaySound
;
503 sndSpew(("Script on %s added sound %s\n", ObjWarnName(CallObjID
), SoundName
));
506 for (int k
= 0; k
< g_ActiveSounds
.Size(); k
++)
507 Assert_(g_ActiveSounds
[k
]->m_iHandle
!= iHandle
);
510 g_ActiveSounds
.Append(t
);
513 sndSpew(("Script on %s failed to play sound %s\n", ObjWarnName(CallObjID
), SoundName
));
519 static bool PlayAndRememberSchema(ObjID SchemaID
,
524 eSoundNetwork Network
)
528 mprintf("Script on %s requested nonexistent schema!\n",ObjWarnName(CallObjID
));
533 const char* name
= pObjSys
->GetName(SchemaID
);
536 strncpy(SchemaLabel
.text
,name
,sizeof(Label
));
537 SchemaLabel
.text
[sizeof(Label
)-1] = '\0';
539 int iHandle
= SndScrptGen(&SchemaLabel
,iFlags
,CallObjID
,TargObjID
,OBJ_NULL
,
540 pCoord
,NULL
,0,(eEnvSoundLoc
)0,kPlaySchema
,
543 if (iHandle
!= SCH_HANDLE_NULL
)
545 cSoundRecord
*t
= new cSoundRecord(iHandle
, pCoord
, CallObjID
, TargObjID
, &SchemaLabel
, TRUE
);
548 t
->m_iFlags
= iFlags
;
549 t
->m_replay
= kPlaySchema
;
551 sndSpew(("Script on %s adding schema %s\n",
552 ObjWarnName(CallObjID
), SchemaLabel
.text
));
554 for (int k
= 0; k
< g_ActiveSounds
.Size(); k
++)
555 Assert_(g_ActiveSounds
[k
]->m_iHandle
!= iHandle
);
558 g_ActiveSounds
.Append(t
);
561 sndSpew(("Script on %s failed to play schema %s\n",
562 ObjWarnName(CallObjID
), SchemaLabel
.text
));
569 static bool PlayAndRememberEnvSchema(ObjID CallObjID
,
575 eEnvSoundLoc loc
= kEnvSoundAmbient
,
576 eSoundNetwork Network
= kSoundNetDefault
)
578 int iHandle
= SndScrptGen(NULL
,iFlags
,CallObjID
,SrcObjID
,Obj2
,pCoord
,pTagSet
,FALSE
,loc
,kPlaySchemaEnv
,Network
);
580 if (iHandle
!= SCH_HANDLE_NULL
)
582 const char* name
= pObjSys
->GetName(SchemaGetIDFromHandle(iHandle
));
584 strncpy(label
.text
,name
,sizeof(label
.text
));
585 label
.text
[sizeof(label
.text
)-1] = '\0';
587 cSoundRecord
*t
= new cSoundRecord(iHandle
,pCoord
,CallObjID
,SrcObjID
,&label
,TRUE
);
589 // @REPLAY - iFlags, loc, Obj2, tags
590 t
->m_iFlags
= iFlags
;
592 t
->m_replay
= kPlaySchemaEnv
;
595 pTagSet
->ToString(&tmp
);
596 strncpy(t
->m_envTagsString
,(const char *)tmp
,MAX_TAG_SIZE
);
599 for (int k
= 0; k
< g_ActiveSounds
.Size(); k
++)
600 Assert_(g_ActiveSounds
[k
]->m_iHandle
!= iHandle
);
603 g_ActiveSounds
.Append(t
);
604 sndSpew(("Script on %s Obj %s Handle %d\n",label
.text
,ObjWarnName(SrcObjID
),iHandle
));
610 if (pTagSet
&& pTagSet
->Size())
613 pTagSet
->ToString(&tmpStr
);
614 sndSpew(("Script on %s failed to play env schema (tags %s)\n", ObjWarnName(CallObjID
), tmpStr
));
617 sndSpew(("Script on %s failed to play env schema\n", ObjWarnName(CallObjID
)));
624 // We can halt all sounds on a given object, or get more specific,
625 // requiring a given sound or schema name and even a callback object.
626 static int HaltActiveSounds(ObjID TargetObjID
,
631 cSoundRecord
*pRecord
;
633 BOOL bAnyName
= FALSE
;
634 BOOL bAnyCallbackObjID
= FALSE
;
637 if (strlen(pszName
) > 15)
638 mprintf("WARNING: HaltActiveSounds: %s longer than 15 characters.\n", pszName
);
644 if (CallbackObjID
== OBJ_NULL
)
645 bAnyCallbackObjID
= TRUE
;
647 // Copy the array as halts will mutate the global array
648 cDynArray
<cSoundRecord
*> activeSounds(g_ActiveSounds
);
651 sndSpew(("Script going to halt for %s\n", ObjWarnName(TargetObjID
)));
652 sndSpew(("Soundlist (size %d)\n", activeSounds
.Size()));
653 for (int k
=0; k
<activeSounds
.Size(); k
++)
654 sndSpew((" on %s, handle %d\n", ObjWarnName(activeSounds
[k
]->m_TargetObjID
), activeSounds
[k
]->m_iHandle
));
657 for (int i
= 0; i
< activeSounds
.Size(); ++i
) {
658 pRecord
= activeSounds
[i
];
660 if ((pRecord
->m_bIsSchema
== bIsSchema
) &&
661 (pRecord
->m_TargetObjID
== TargetObjID
) &&
662 (bAnyName
|| (strcmp(pszName
, pRecord
->m_Name
.text
) == 0)) &&
663 (bAnyCallbackObjID
|| (pRecord
->m_CallbackObjID
== CallbackObjID
)))
665 sndSpew(("Script Halting %s%s for obj %s (cback obj %s) handle %d\n",
666 pszName
[0]=='\0'?"Unknown":pszName
,
667 bIsSchema
?" (a Schema)":" (a Sound)",
668 ObjWarnName(TargetObjID
),ObjWarnName(CallbackObjID
),pRecord
->m_iHandle
));
671 SchemaPlayHalt(pRecord
->m_iHandle
);
673 g_pPropSnd
->SoundHalt(pRecord
->m_iHandle
);
683 IMPLEMENT_SCRMSG_PERSISTENT(sSoundDoneMsg
)
685 PersistenceHeader(sScrMsg
, kSoundDoneMsgVer
);
686 Persistent(coordinates
);
687 Persistent(targetObject
);
694 IMPLEMENT_SCRMSG_PERSISTENT(sSchemaDoneMsg
)
696 PersistenceHeader(sScrMsg
, kSchemaDoneMsgVer
);
697 Persistent(coordinates
);
698 Persistent(targetObject
);
704 ///////////////////////////////////////////////////////////////////////////////
706 // CLASS: cDebugScrSrv
710 DECLARE_SCRIPT_SERVICE_IMPL(cSoundScrSrv
, Sound
)
714 ////////////////////////////////////
716 // four routines for playing sounds...
719 // If we do not have a target object or set of coordinates, we
720 // assume our sound is coming from the object playing the script.
721 STDMETHOD_ (boolean
, Play
)(object CallbackObjID
,
722 const string ref SoundName
,
723 eSoundSpecial Special
= kSoundNormal
,
724 eSoundNetwork Network
= kSoundNetDefault
)
727 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
728 Position
*Pos
= ObjPosGet(ScriptID
);
729 mxs_vector Coordinates
;
732 mx_zero_vec(&Coordinates
);
734 Coordinates
= Pos
->loc
.vec
;
736 return PlayAndRememberSound(SoundName
, ScriptID
, ScriptID
,
737 &Coordinates
, FALSE
, Special
, Network
);
740 // We'll record the coordinates of the target object. Naturally,
741 // this doesn't keep it from moving before the sound finishes.
742 STDMETHOD_ (boolean
, Play
)(object CallbackObjID
,
743 const string ref SoundName
,
745 eSoundSpecial Special
= kSoundNormal
,
746 eSoundNetwork Network
= kSoundNetDefault
)
748 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
749 ObjID TargetID
= ScriptObjID(TargetObj
);
750 Position
*Pos
= ObjPosGet(TargetID
);
751 mxs_vector Coordinates
;
754 mx_zero_vec(&Coordinates
);
756 Coordinates
= Pos
->loc
.vec
;
758 return PlayAndRememberSound(SoundName
, ScriptID
, TargetID
,
759 &Coordinates
, FALSE
, Special
, Network
);
762 // We set the target object to OBJ_NULL if we're playing to
764 STDMETHOD_ (boolean
, Play
)(object CallbackObjID
,
765 const string ref SoundName
,
767 eSoundSpecial Special
= kSoundNormal
,
768 eSoundNetwork Network
= kSoundNetDefault
)
770 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
771 return PlayAndRememberSound(SoundName
, ScriptID
, OBJ_NULL
,
772 &Location
, FALSE
, Special
, Network
);
775 STDMETHOD_ (boolean
, PlayAmbient
)(object CallbackObjID
,
776 const string ref SoundName
,
777 eSoundSpecial Special
= kSoundNormal
,
778 eSoundNetwork Network
= kSoundNetDefault
)
780 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
781 mxs_vector Coordinates
;
782 mx_zero_vec(&Coordinates
);
784 return PlayAndRememberSound(SoundName
, ScriptID
, ScriptID
,
785 &Coordinates
, TRUE
, Special
, Network
);
788 ////////////////////////////////////
790 // four routines for playing schemas
792 STDMETHOD_ (boolean
, PlaySchema
)(object CallbackObjID
,
794 eSoundNetwork Network
= kSoundNetDefault
)
796 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
797 Position
*Pos
= ObjPosGet(ScriptID
);
798 mxs_vector Coordinates
;
801 mx_zero_vec(&Coordinates
);
803 Coordinates
= Pos
->loc
.vec
;
805 return PlayAndRememberSchema(Schema
, ScriptID
, ScriptID
,
806 &Coordinates
, SCH_SET_OBJ
, Network
);
809 STDMETHOD_ (boolean
, PlaySchema
)(object CallbackObjID
,
812 eSoundNetwork Network
= kSoundNetDefault
)
814 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
815 ObjID TargetID
= ScriptObjID(TargetObj
);
816 Position
*Pos
= ObjPosGet(TargetID
);
817 mxs_vector Coordinates
;
820 mx_zero_vec(&Coordinates
);
822 Coordinates
= Pos
->loc
.vec
;
824 return PlayAndRememberSchema(Schema
, ScriptID
, TargetID
,
825 &Coordinates
, SCH_SET_OBJ
, Network
);
828 STDMETHOD_ (boolean
, PlaySchema
)(object CallbackObjID
,
831 eSoundNetwork Network
= kSoundNetDefault
)
833 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
834 return PlayAndRememberSchema(Schema
, ScriptID
, OBJ_NULL
,
835 &Location
, SCH_SET_LOC
, Network
);
838 STDMETHOD_ (boolean
, PlaySchemaAmbient
)(object CallbackObjID
,
840 eSoundNetwork Network
= kSoundNetDefault
)
842 ObjID ScriptID
= ScriptObjID(CallbackObjID
);
843 mxs_vector Coordinates
;
844 mx_zero_vec(&Coordinates
);
846 return PlayAndRememberSchema(Schema
, ScriptID
, ScriptID
,
847 &Coordinates
, 0, Network
);
851 STDMETHOD_(boolean
, PlayEnvSchema
)(object CallbackObject
,
852 const string ref Tags
,
853 object SourceObject
, object Agent
,
854 eEnvSoundLoc loc
= kEnvSoundAmbient
,
855 eSoundNetwork Network
= kSoundNetDefault
)
857 cTagSet
TagSet(Tags
);
859 ObjID ScriptID
= ScriptObjID(CallbackObject
);
860 ObjID SourceID
= ScriptObjID(SourceObject
);
861 if (SourceID
== OBJ_NULL
)
863 Position
*Pos
= ObjPosGet(SourceID
);
864 mxs_vector Coordinates
;
867 Coordinates
= Pos
->loc
.vec
;
869 mx_zero_vec(&Coordinates
);
871 ulong flags
= (loc
== kEnvSoundOnObj
) ? SCH_SET_OBJ
: 0;
873 return PlayAndRememberEnvSchema(ScriptID
,
885 STDMETHOD_(boolean
, PlayVoiceOver
)(object cb_obj
, object schema
)
887 AutoAppIPtr(VoiceOverSys
);
889 int iHandle
= pVoiceOverSys
->Play(schema
);
891 if (iHandle
!= SCH_HANDLE_NULL
)
895 ConfigSpew("ScriptSoundSpew",("Script on object %d failed to play schema %d"));
902 ////////////////////////////////////
904 // two routines to undo the stuff the other ones do
907 STDMETHOD_(integer
, Halt
)(object TargetObject
,
908 const string ref SoundName
,
909 object CallbackObject
)
911 return HaltActiveSounds(TargetObject
, SoundName
, CallbackObject
, FALSE
);
914 STDMETHOD_(boolean
, HaltSchema
)(object TargetObject
,
915 const string ref SchemaName
,
916 object CallbackObject
)
918 return HaltActiveSounds(TargetObject
, SchemaName
, CallbackObject
, TRUE
);
922 STDMETHOD(HaltSpeech
)(object speakerObj
)
924 SpeechHalt(speakerObj
);
928 STDMETHOD_(boolean
,PreLoad
)(const string ref SpeechName
)
930 return SFX_PreLoad(SpeechName
);
934 IMPLEMENT_SCRIPT_SERVICE_IMPL(cSoundScrSrv
, Sound
);
936 ///////////////////////////////////////////////////////////////////////////////