mod_TimerRepeat.hsp

common\ mod_TimerRepeat.hsp

//
//	mod_uniq.hsp - ver.1.1											by MIZUSHIKI
//
#ifndef uniq_start

#define global uniq_start %tunique %i0
#define global ctype uniq(%1) %tunique %1@%p
#define global ctype uniq2(%1) %tunique %1@%p1
#define global ctype uniq3(%1) %tunique %1@%p2
#define global ctype uniq4(%1) %tunique %1@%p3
#define global ctype uniq5(%1) %tunique %1@%p4
#define global ctype uniq6(%1) %tunique %1@%p5
#define global ctype uniq7(%1) %tunique %1@%p6
#define global ctype uniq8(%1) %tunique %1@%p7
#define global ctype uniq9(%1) %tunique %1@%p8
#define global uniq_end %tunique %o0

#endif

//
//	mod_TimerRepeat.hsp - ver.2.5									by MIZUSHIKI
//
#ifndef timer_repeat

#define global timer_repeat(%1=10,%2=-1,%3=0,%4=0) %t__timer if pChk@modTimerRepeat("%1"){dup _arA@modTimerRepeat,%1}else{vaA@modTimerRepeat=%1:dup _arA@modTimerRepeat,vaA@modTimerRepeat}:_setTimerLabel@modTimerRepeat %2,%3,*%i,%4 :goto *%i :*%p1 :uniq_start:if(_TimerRepeat_deinit_@modTimerRepeat<=1){uniq(_timer_cnt_@modTimerRepeat)=_TimerRepeat_cnt_@modTimerRepeat}:if _dupdim_@modTimerRepeat>-2{ if _dupdim_@modTimerRepeat>=0{dim uniq(timer_intervals@modTimerRepeat),_dupdim_@modTimerRepeat}: dup _ari@modTimerRepeat,uniq(timer_intervals@modTimerRepeat):return} :if(_TimerRepeat_deinit_@modTimerRepeat<=1) {
#define global timer_init %t__timer *%o :if(_TimerRepeat_init_@modTimerRepeat>=1) { uniq(_timer_cnt_@modTimerRepeat)=_getTimerFCnt_Label@modTimerRepeat(*%p0) :
#define global _init_end %t__timer _TimerRepeat_init_@modTimerRepeat=-1}:if(_TimerRepeat_init_@modTimerRepeat==-1) {goto *%i}
#define global timer_deinit } : if(_TimerRepeat_deinit_@modTimerRepeat>=1) {
#define global _deinit_end } : if(_TimerRepeat_deinit_@modTimerRepeat<=1) {
#define global timer_loop %t__timer } :uniq_end :return :*%o :_get_index@modTimerRepeat *%o
/*
- 基本の型 ---------------------------------------------------------------------
	[timer_repeat] ->  SetLabel(*A) : goto *B : *A : if(_deinit_<=1){
	                       (定期的処理)
	[timer_loop] ->    } : return : *B

	・timer_repeatスクリプト実行時はSetLabelでrepeat間隔とかを保存するだけ。最初はgoto *Bでtimer_loopまで飛び内部の処理はされない。
	・時間になったら *A が呼ばれる (_deinit_==0)

- initあり ---------------------------------------------------------------------
	[timer_repeat] ->  SetLabel(*A) : goto *B : *A : if(_deinit_<=1){
	[timer_init:]  ->      *B : if(_init_>=1) {
	                           (初期化処理)
	[_init_end]    ->      _init_=-1 } : if(_init_==-1){ goto *C }
	                       (定期的処理)
	[timer_loop]   ->  } : return : *C

	・SetLabelしたとき_init_=1になり、その後のgoto *Bはtimer_init:前まで飛び(初期化処理)が実行される。その処理の後goto *Cされる。(_deinit_==0)
	・時間になったら *A が呼ばれる (_deinit_==0, _init_==0)

- deinitあり -------------------------------------------------------------------
	[timer_repeat] ->  SetLabel(*A) : goto *B : *A : if(_deinit_<=1){
	                       (定期的処理)
	[timer_deinit] ->  } : if(_deinit_>=1) {
	                       (後始末処理)
	[timer_loop]   ->  } : return : *B

	・時間になったら *A が呼ばれる (_deinit_==0, _init_==0)
	・timer_repeatを回数指定した場合、最後の回は_deinit_=1になり(定期的処理)(後始末処理)両方実行される。
	・timer_killされたとき_deinit_=2で *A が呼ばれ、(後始末処理)だけが実行される。
*/
#define global timer_break %t__timer _killTimerLabel_Label@modTimerRepeat *%p1 :return
#define global timer_continue(%1=-1,%2=0) %t__timer _continueTimerCount_Label@modTimerRepeat *%p1,%1 :_continueTimerTimesReset_Label@modTimerRepeat *%p1,%2 :return
#define global timer_cnt uniq(_timer_cnt_@modTimerRepeat)

#define global timer_setTimerSpeed(%1=__timer__id__@modTimerRepeat,%2=10) __timer__temp__@modTimerRepeat=%1 : if pChk@modTimerRepeat("%2"){dup _arA@modTimerRepeat,%2}else{vaA@modTimerRepeat=%2:dup _arA@modTimerRepeat,vaA@modTimerRepeat}: _setTimerSpeed@modTimerRepeat __timer__temp__@modTimerRepeat
#define global timer_kill(%1=__timer__id__@modTimerRepeat) __timer__temp__@modTimerRepeat=%1 : _killTimerLabel@modTimerRepeat __timer__temp__@modTimerRepeat
#define global ctype timer_getTimerTime(%1=__timer__id__@modTimerRepeat) _get_timertime@modTimerRepeat(%1)

#define global ctype timer_getTime timeGetTime@modTimerRepeat()
#define global timer_intervals uniq(timer_intervals@modTimerRepeat)


#module modTimerRepeat
#deffunc _init_@modTimerRepeat
	//デバッガに怒られないよう一応初期化
	labels=0
	ing=0
	usingengine=0
	mae_nft=0
	st=0
	_ara=0
	_arb=0
	_dupdim_=-2
	_ari=0
	return
#defcfunc timeGetTime@modTimerRepeat
#ifndef _HSP3DISH
	#uselib "winmm.dll"
	#cfunc _timeGetTime@modTimerRepeat "timeGetTime"
	return _timeGetTime@modTimerRepeat()
#else
	getreq time24, SYSREQ_TIMER
	return time24
#endif


#deffunc _setTimerLabel@modTimerRepeat int num, int fcnt, label _label, int type
	;_arA(第5パラメータ)  ; 繰り返し間隔のミリ秒(アニメーションの時は各フレーム間の時間間隔の配列になる)
	label = _label
	if vartype(labels) != 1 {
		// 初期化処理
		ldim labels,1
	}
	//既に存在してing中だったら、typeに合わせて無効か終了か終了+再リピートか
	index = 0
	repeat length.labels-1, 1
		if lpeek(labels.cnt,0) == lpeek(label,0) :index=cnt :break
	loop
	if index!=0 {
		if ing(index) == 1 {
			switch type
				case 1 ://終了のみ
					timer_kill label       ; timer_deinit内処理を実行
					_TimerRepeat_init_=-1  ; timer_repeat内処理すべてすっ飛ばす(timer_init:があっても)
					return
					swbreak
				case 2 ://終了+再リピート
					timer_kill label       ; timer_deinit内処理を実行
					swbreak
				default ://無効
					_TimerRepeat_init_=-1  ; timer_repeat内処理すべてすっ飛ばす(timer_init:があっても)
					return
			swend
		}
	}else {
		index = length.labels
	}

	nums(index) = num : if nums(index)<0 :nums(index)=-1
	fcnts(index) = fcnt
	labels(index) = label
	cnts(index) = fcnt
	;intervals(index) = time                ; 各timer_repeat内のuniq(timer_intervals@modTimerRepeat)に書くようにした
	SetINTERVAL@modTimerRepeat index, _arA  ; uniq(timer_intervals@modTimerRepeat)に_arAを書き込みに行く
	times(index) = timeGetTime()
	times_lastFire(index) = times(index)
	ing(index) = 1 : if num == 0 : ing(index) = 0
	engine(index) = usingEngine

	_TimerRepeat_init_=1  ; timer_init内を実行(timer_init:指示があれば)
	return
//
//  _TimerRepeat_init_  ; timer_repeat実行時に影響
//    0 : 通常時
//    1 : timer_repeatされて登録されたとき1になりtimer_init内が実行される。init内の最後で-1になる。
//   -1 : timer_repeatされたとき既に処理中だと-1になる。-1だとtimer_init内処理がすっ飛ばされた後、さらにtimer_loopまですっ飛ばされて timer_repeaat〜timer_loop までの処理が実行されないで終わる。(timer_init:があっても)
//
//  _TimerRepeat_deinit_  ; timer_fire実行時に影響
//    0 : 通常時
//    1 : timer_fireが発動して最後の回数のとき1になりtimer_deinit内"も"実行される。(timer_repeatで回数制限を指定している場合)
//    2 : timer_killでlabelが実行されて、timer_deinit: の中だけ実行されて欲しいとき。
//
#defcfunc GetINTERVAL@modTimerRepeat int i
	_dupdim_=-1
	gosub labels(i)
	_dupdim_=-2
	return _ari(cnts(i)\(length._ari))
#deffunc SetINTERVAL@modTimerRepeat int i, array ar
	_dupdim_=length(ar)
	gosub labels(i)
	_dupdim_=-2
	foreach ar
		_ari(cnt) = ar(cnt)
	loop
	return
//
//  _dupdim_ = -2 : 通常時
//           = -1 : gosub labels(i)でtimer_repeat先に飛んで dup _ari, uniq(timer_intervals) して戻ってくる。つまり飛んだ先の uniq(timer_intervals) を貰いに行く為のフラグ。
//          >=  0 : gosub labels(i)でtimer_repeat先に飛んで dim uniq(timer_intervals), _dupdim_ : dup _ari, uniq(timer_intervals)して戻ってくる。つまり飛んだ先で uniq(timer_intervals) を初期化+戻った後に _ari に必要分の配列データを書き込む。
//
#define global timer_fire(%1=1) _timer_fire %1
#deffunc _timer_fire int type
	nowTime = -1; = timeGetTime()
	foreach ing
		if ing(cnt) == 0 :continue
		if type != 2 : if engine(cnt) != type :continue 
		if nowTime==-1 : nowTime = timeGetTime()
		if nowTime - times_lastFire(cnt) >= GetINTERVAL@modTimerRepeat(cnt) : __timer__id__ = cnt : times_lastFire(cnt) = nowTime : gosub *__timer__WaitLoop__@modTimerRepeat
	loop
	return
	
*__timer__WaitLoop__@modTimerRepeat
	_TimerRepeat_deinit_ = 0
	if nums(__timer__id__) != -1 {
		if cnts(__timer__id__) - fcnts(__timer__id__) >= nums(__timer__id__) - 1 {
			if cnts(__timer__id__) - fcnts(__timer__id__) >= nums(__timer__id__) :return //もし最後超えても次が来たとき止める。
			_TimerRepeat_deinit_ = 1
		}
	}
	_TimerRepeat_init_ = 0  ; timer_init 内は実行しない
	_TimerRepeat_cnt_ = cnts(__timer__id__) : cnts(__timer__id__)++
	if _TimerRepeat_deinit_ = 1 : ing(__timer__id__) = 0  ; この処理を最後にこのtimer_repeatは終了
	gosub labels(__timer__id__)
	return
#deffunc _killTimerLabel_Label@modTimerRepeat label _label
	label = _label
	_killTimerLabel@modTimerRepeat label
	return
#deffunc _killTimerLabel@modTimerRepeat var v
	if vartype(v)==1{
		index = 0
		repeat length.labels-1, 1
			if lpeek(labels.cnt,0) == lpeek(v,0) :index=cnt :break
		loop
		if index=0 :return
	}else {
		index = v
		if index = 0 :return
	}
	if length(labels)<=index :return
	
	if ing(index) == 0 :return
	__timer__id__ = index
	_TimerRepeat_deinit_ = 2
	_TimerRepeat_cnt_ = cnts(index)
	ing(index) = 0
	gosub labels(index)
	_TimerRepeat_deinit_ = 0
	return
#deffunc _AllKillTimerLabel onexit
	foreach ing
		ing(cnt) = 0
	loop
	return

#deffunc timer_setTimerEngine int type
	usingEngine = (type == 1)
	return

#defcfunc _getNextFireTime@modTimerRepeat int type
	if type=1 : return mae_NFT ;
	_NFT = 2147483647
	foreach ing
		if ing(cnt) == 0 :continue
		if _NFT > times_lastFire(cnt)+GetINTERVAL@modTimerRepeat(cnt) : _NFT = times_lastFire(cnt)+GetINTERVAL@modTimerRepeat(cnt)
	loop
	if _NFT == 2147483647 : return -1
	mae_NFT = _NFT - timeGetTime() 
	if mae_NFT<0 : mae_NFT=0
	return mae_NFT
	
#deffunc _setTimerSpeed@modTimerRepeat var v;, int time
	if vartype(v)==1{
		index = 0
		repeat length.labels-1, 1
			if lpeek(labels.cnt,0) == lpeek(v,0) :index=cnt :break
		loop
		if index=0 :return
	}else {
		index = v
		if index = 0 :return
	}
	if length(labels)<=index :return
	SetINTERVAL@modTimerRepeat index, _arA
	;intervals(index) = time
	return

#deffunc _continueTimerCount_Label@modTimerRepeat label _label, int count
	_continueTimerCount@modTimerRepeat _getc_index@modTimerRepeat(_label), count
	return
#deffunc _continueTimerCount@modTimerRepeat int i, int count
	if count != -1 {
		cnts(i) = count
	}
	return
#deffunc _continueTimerTimesReset_Label@modTimerRepeat label _label, int bool
	_continueTimerTimesReset@modTimerRepeat _getc_index@modTimerRepeat(_label), bool
	return
#deffunc _continueTimerTimesReset@modTimerRepeat int i, int bool
	if bool=0 :return
	times(i) = timeGetTime()
	return
	
#deffunc _get_index@modTimerRepeat label _label
	label = _label
	index = 0
	repeat length.labels-1, 1
		if lpeek(labels.cnt,0) == lpeek(label,0) :index=cnt :break
	loop
	if index=0 :return
	mref st,64
	st = index
	return
	
#defcfunc _getTimerFCnt_Label@modTimerRepeat label _label
	return fcnts( _getc_index@modTimerRepeat(_label) )
	
#defcfunc _getc_index@modTimerRepeat label _label
	label = _label
	index = 0
	repeat length.labels-1, 1
		if lpeek(labels.cnt,0) == lpeek(label,0) :index=cnt :break
	loop
	if index=0 :return 0
	return index
	
#defcfunc _get_timertime@modTimerRepeat int _index
	if _index <= 0 :return -1
	if length(labels)<=_index :return -1
	
	if ing(_index) = 0 :return -1
	return (timeGetTime@modTimerRepeat() - times@modTimerRepeat(_index))
	
#define global timer_ease(%1,%2,%3,%4,%5) if pChk@modTimerRepeat("%2"){dup _arA@modTimerRepeat,%2}else{vaA@modTimerRepeat=%2:dup _arA@modTimerRepeat,vaA@modTimerRepeat}:if pChk@modTimerRepeat("%3"){dup _arB@modTimerRepeat,%3}else{vaB@modTimerRepeat=%3:dup _arB@modTimerRepeat,vaB@modTimerRepeat} : _TimerRepeat_easing@modTimerRepeat %1,timeGetTime@modTimerRepeat(),times@modTimerRepeat(__timer__id__@modTimerRepeat),%4,%5
#define global geteaseT(%1,%2,%3,%4,%5,%6,%7)  if pChk@modTimerRepeat("%3"){dup _arA@modTimerRepeat,%3}else{vaA@modTimerRepeat=%3:dup _arA@modTimerRepeat,vaA@modTimerRepeat}:if pChk@modTimerRepeat("%5"){dup _arB@modTimerRepeat,%5}else{vaB@modTimerRepeat=%5:dup _arB@modTimerRepeat,vaB@modTimerRepeat} : _TimerRepeat_easing@modTimerRepeat %1,%2,%4,%6,%7
#define global geteaseWithTime(%1,%2,%3,%4,%5,%6,%7) geteaseT %1,%2,%3,%4,%5,%6,%7
//関数に渡されたパラメータが変数か確認する
#defcfunc pChk@modTimerRepeat str _chkStr
	chkStr = _chkStr
	chkStr = strtrim(chkStr,3)
	// uniq()だけ殻割する特殊仕様
	if lpeek(chkStr,0)==1902734965 { ;uniq
		if wpeek(chkStr,3)==10353 { ;q(
			if peek(chkStr,strlen(chkStr)-1)=')' {;uniq(〜)
				chkStr = strmid(chkStr,5,strlen(chkStr)-6)
				chkStr = strtrim(chkStr,3)
			}
		}
	}
	flg = 0
	repeat strlen(chkStr)
		if 'a'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='z' :flg=1 :continue
		if 'A'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='Z' :flg=1 :continue
		if peek(chkStr,cnt)=='_' :flg=1 :continue
		if peek(chkStr,cnt)=='@' :flg=1 :continue
		if flg=0 : break
		if '0'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='9' :continue
		flg = 0 : break
	loop
	return flg
	
#deffunc _TimerRepeat_easing@modTimerRepeat array arZ, int _miriSecZ, int _miriSecA, int type, int _miriSec
	miriSec  = _miriSec  :if miriSec  <= 0 :miriSec  = 1
	miriSecA = _miriSecA ;:if miriSecA <  0 :miriSecA = 0 //マイナス値もありえる。(24.855日以上たつとなる。差分をとっているだけなので問題ない)
	miriSecZ = _miriSecZ :if miriSecZ < miriSecA :miriSecZ = miriSecA
	if length(_arA) != length(_arB) : return -1.0
	dimtype arZ, vartype(_arB), length(_arB)
	repeat length(_arB)
		setease _arA(cnt), _arB(cnt), type
		if vartype(_arB) == 3 {
			arZ(cnt) = geteasef( miriSecZ-miriSecA, miriSec )
		}else {
			arZ(cnt) = getease( miriSecZ-miriSecA, miriSec )
		}
	loop
	per = 1.0*( miriSecZ-miriSecA ) / miriSec
	if ( per > 1.0 ) || ( per < 0.0 ) : per = 1.0
	return per


//
//	mod_waiton.hsp(+タイマーループ割り込み) - ver.1.2.2					by MIZUSHIKI
//
#define global timer_waiton(%1=100) :\
	_waitTime_@modTimerRepeat = timeGetTime@modTimerRepeat() :\
	_whilecount_@modTimerRepeat=0:\
	while 1 :\
		_nokoriTime_@modTimerRepeat=%1-(timeGetTime@modTimerRepeat() - _waitTime_@modTimerRepeat)/10 :\
		_nokoriTime_2@modTimerRepeat = _nokoriTime_@modTimerRepeat :\
		if(_getNextFireTime@modTimerRepeat(0)!=-1 && _nokoriTime_2@modTimerRepeat>_getNextFireTime@modTimerRepeat(1)/10){ _nokoriTime_2@modTimerRepeat=_getNextFireTime@modTimerRepeat(1)/10 } :\
		if(_whilecount_@modTimerRepeat==0||_nokoriTime_2@modTimerRepeat>1){if(_nokoriTime_2@modTimerRepeat<=0){_nokoriTime_2@modTimerRepeat=1}:wait@hsp _nokoriTime_2@modTimerRepeat} :\
		timer_fire 0 :\
		if(_nokoriTime_@modTimerRepeat<=0){ _break } :\
		_whilecount_@modTimerRepeat++:\
	wend :\
	_awaitTime_@modTimerRepeat=timeGetTime@modTimerRepeat()

#define global timer_awaiton(%1=0) :\
	if(_awaitTime_@modTimerRepeat=0){ _awaitTime_@modTimerRepeat = timeGetTime@modTimerRepeat() } :\
	_whilecount_@modTimerRepeat=0:\
	while 1 :\
		_nokoriTime_@modTimerRepeat=%1-(timeGetTime@modTimerRepeat() - _awaitTime_@modTimerRepeat) :\
		_nokoriTime_2@modTimerRepeat = _nokoriTime_@modTimerRepeat :\
		if(_getNextFireTime@modTimerRepeat(0)!=-1 && _nokoriTime_2@modTimerRepeat>_getNextFireTime@modTimerRepeat(1)){ _nokoriTime_2@modTimerRepeat=_getNextFireTime@modTimerRepeat(1) } :\
		if(_whilecount_@modTimerRepeat==0||_nokoriTime_2@modTimerRepeat>1){if(_nokoriTime_2@modTimerRepeat<=0){_nokoriTime_2@modTimerRepeat=1}:await@hsp _nokoriTime_2@modTimerRepeat} :\
		timer_fire 0 :\
		if(_nokoriTime_@modTimerRepeat<=0){ _break } :\
		_whilecount_@modTimerRepeat++:\
	wend :\
	_awaitTime_@modTimerRepeat=timeGetTime@modTimerRepeat()

#define global timer_stop(%1=dummy) :\
	_awaitTime_@modTimerRepeat=0 :\
	_stop_word_@modTimerRepeat="%1":\
	_s_w_nine_@modTimerRepeat=9*(strmid(_stop_word_@modTimerRepeat,-1,4)=="wait"):\
	_whilecount_@modTimerRepeat=0:\
	while 1 :\
		_nokoriTime_2@modTimerRepeat = 214748364 :\
		if(_getNextFireTime@modTimerRepeat(0)!=-1){ _nokoriTime_2@modTimerRepeat=_getNextFireTime@modTimerRepeat(1) } :\
		if(_whilecount_@modTimerRepeat==0||_nokoriTime_2@modTimerRepeat>(1+_s_w_nine_@modTimerRepeat)){if(_s_w_nine_@modTimerRepeat==0){if(_nokoriTime_2@modTimerRepeat<=0){_nokoriTime_2@modTimerRepeat=1}:await@hsp _nokoriTime_2@modTimerRepeat}else{if(_nokoriTime_2@modTimerRepeat<=9){_nokoriTime_2@modTimerRepeat=10}:wait@hsp _nokoriTime_2@modTimerRepeat/10}} :\
		timer_fire 0 :\
	wend
	
	#undef wait
	#define global wait timer_waiton
	#undef await
	#define global await timer_awaiton
	#undef stop
	#define global stop timer_stop

#global
_init_@modTimerRepeat
#endif