←  Problemy

AMXX.pl: Support AMX Mod X i SourceMod

»

[ROZWIĄZANE] Poruszanie entem wg. klawiszy...

Locked

  • +
  • -
NoLiFeR's Photo NoLiFeR 26.02.2016

Witam, mam dość nietypowy problem, dotyczy on poruszania się entity.

Za pomocą pluginu tworzę enta, ustawiam mu odpowiednie movetype i solid (TOSS i SLIDEBOX), jednak próba zrobienia sterowania nie wychodzi mi najlepiej :/ Ktoś ma jakieś pomysły ? Mój obecny kod



public UpgradePosition(ent)
{
	new id = 0;
	for(new i=0;i<33;i++)
		if(ent == entskrz[i]) {
			id = i
			break;
		}
	if(id == 0)
		return FMRES_IGNORED;
		
	if(!is_user_alive(id)) {
		entity[id] = 0
		remove_entity(ent)
		if(is_user_connected(id)) {
			set_user_rendering(id, kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 255);
			attach_view( id, id );
		}
		przemieniony[id] = false;
		return FMRES_IGNORED;
	}
	new buttons = get_user_button(id)
	if(buttons & IN_USE) {
		if(!nieruszalny[id] && licznik[id] == -1)
			licznik[id] = 10;
		
		else if(!nieruszalny[id] && licznik[id] > 0)
			licznik[id]--
			
		else if(!nieruszalny[id] && licznik[id] == 0)
			nieruszalny[id] = true;
			
		else nieruszalny[id] = false;
	}
	if(nieruszalny[id]) {
		entity_set_float(ent, EV_FL_nextthink, get_gametime());
		return FMRES_IGNORED;
	}
	new Float:Angles[3]
	pev(id, pev_angles, Angles)
	Angles[0] = 0.0
	Angles[2] = 0.0
	set_pev(ent, pev_angles, Angles)
	set_user_health(id, pev(ent, pev_health))
	new Float:velocity[3];
	pev(ent, pev_velocity, velocity)
	new Float:old2vel = velocity[2]
		
	new Float:fector[4][3];
	new bool:old = false;
	if((buttons & IN_FORWARD) || (buttons & IN_BACK) || (buttons & IN_RIGHT) || (buttons & IN_LEFT)) {
		new count = 0; 
		new bool:zm_p[4]
		if(buttons & IN_BACK && !(buttons & IN_FORWARD)) {
			angle_vector (Angles, ANGLEVECTOR_FORWARD, fector[0])
			count++
			zm_p[0] = true;
		}
		if(buttons & IN_FORWARD && !(buttons & IN_BACK)) {
			angle_vector (Angles, ANGLEVECTOR_FORWARD, fector[0])
			xs_vec_neg(fector[0],fector[1])
			count++
			zm_p[1] = true;
		}
		if(buttons & IN_LEFT && !(buttons & IN_RIGHT)) {
			angle_vector (Angles, ANGLEVECTOR_RIGHT,fector[2])
			count++
			zm_p[2] = true;
		}
		if(buttons & IN_RIGHT && !(buttons & IN_LEFT)) {
			angle_vector (Angles, ANGLEVECTOR_RIGHT,fector[2])
			xs_vec_neg(fector[2],fector[3])
			count++
			zm_p[3] = true;
		}
		
		new Float:speed = 250.0 / count
		if(count == 0)
			old = true;
		else if(count == 1){
			new ktoraz = -1
			for(new i=0;i<4;i++) {
				if(zm_p[i]) {
					xs_vec_mul_scalar( fector[i] , speed , fector[i] ); 
					ktoraz = i
					break;
				}
			}
			for(new i=0;i<3;i++)
				velocity[i] = fector[ktoraz][i]
		}
		else if(count == 2){
			new bool:ilosczm = false;
			new bool:ktoraz[2]
			for(new i=0;i<4;i++) {
				if(zm_p[i]) {
					xs_vec_mul_scalar( fector[i] , speed , fector[i] ); 
					ktoraz[i > 1 ? 1 : 0] = i%2 == 1 ? true : false
					if(ilosczm)
						break;
					else
						ilosczm = true;
				}
			}
			for(new i=0;i<3;i++)
				velocity[i] = floatdiv(floatadd(fector[ktoraz[0] ? 1 : 0][i], fector[ktoraz[0] ? 3 : 2][i]), 2.0)
		}
	}
	if(old) {
		entity_set_float(ent, EV_FL_nextthink, get_gametime());
		return FMRES_IGNORED;
	}
	
	velocity[2] = old2vel + 0.05
	
	if(!(get_user_oldbutton(id) & IN_JUMP) && buttons & IN_JUMP && pev(ent, pev_flags) & FL_ONGROUND)
		velocity[2] = random_float(25.0, 26.0)
		
	if(!(buttons & IN_BACK) && !(buttons & IN_FORWARD) && !(buttons & IN_RIGHT) && !(buttons & IN_LEFT)) {
		entity_set_float(ent, EV_FL_nextthink, get_gametime());
		return FMRES_IGNORED;
	}
	
	set_pev(ent,pev_velocity,velocity)
	entity_set_float(ent, EV_FL_nextthink, get_gametime());
	return FMRES_IGNORED;
}

// EDIT po to żeby przestawić new buttons = get_user_button(id) z warunkiem czy gracz jest żywy

 

 

sprawia że entity po wciśnięciu w, a, s lub d po prostu staje w miejscu, nic nie da się z nią zrobić (z samym thinkiem wszystko w porządku, bo obraca bytem co mogę zaobserwować)

Czy możliwe jest że funkcja jest zbudowana źle i po prostu entity "klinuje się" w ziemi ?

Dziękuje.


Edited by NoLiFeR, 26.02.2016 22:37.
Quote

  • +
  • -
DarkGL's Photo DarkGL 27.02.2016

Najpierw to zrób prościej bo obecnie wygląda to strasznie dopiero wtedy przystąpimy do poprawy

Quote

  • +
  • -
NoLiFeR's Photo NoLiFeR 27.02.2016

Nie mam pojęcia jak można to zrobić prościej.. :/ Pewnie nie widze najprostszego rozwiązania...

Quote

  • +
  • -
grankee's Photo grankee 28.02.2016

Prawdę mówiąc jest tu nasrane dużo kodu i ciężko z niego jasno wywnioskować co ma on dokładnie robić i w jakich okolicznościach.

Kilka wskazówek jak ułatwić innym a także sobie w przyszłości odszyfrowanie kodu (dziś ogarniasz, bo dopiero co go pisałeś, ale za kilka tygodni/miesięcy jak zapragniesz coś zmienić to się pogubisz):

-nazywaj zmienne zgodnie z ich przeznaczeniem-używaj pełnych nazw a nie skrótów, które tylko Ty rozumiesz, nawet jeśli nazwa będzie przez to dłuższa.

-używaj przedrostków sugerujących typ zmiennej w jej nazwie (dużo lepiej czyta się vecSpeed, iCount,szClass niż speed, count,class)

-! używaj komentarzy jak najwięcej, na prawdę dużo można po nich wywnioskować

-podajesz tylko jedną funkcję, która nie wiadomo kiedy się wykonuje i używasz w niej zmiennych, które nie wiadomo co przechowują, można jedynie wywnioskować, że skoro ich deklaracji nie ma wewnątrz to są globalne, ale gdzie i kiedy są jeszcze modyfikowane to nie wiadomo.

 

 

Konicznie opisz jaki player i jak ma sterować no i czym oczywiście. Podaj szczegóły dotyczące bytu sterowanego, jak ma wyglądać i jak się poruszać, jakiej jest klasy, po prostu co możesz. No i popraw ten kod bo faktycznie nie jest dobrze...


Edited by grankee, 28.02.2016 16:42.
Quote

  • +
  • -
NoLiFeR's Photo NoLiFeR 28.02.2016

A więc tak. Zastosowałem się do Waszych porad, i napisałem osobną funkcje na ten cel, na razie bez skakania, aby nie zaciemniać kodu.
Myśle jednak że to nie wina funkcji, a samego enta.
 


public poruszanie(ent, id, Float:Angles[3], buttons) {
	new Float:vecVelocity[3];
	//pev(ent, pev_velocity, vecVelocity)
//	new Float:f_OldFallVelocity = vecVelocity[2]
		
	new iCount = 0; 
	new Float:Temp[3]
	// W && !S
	if(buttons & IN_FORWARD && !(buttons & IN_BACK)) {
		angle_vector (Angles, ANGLEVECTOR_FORWARD, Temp)
		xs_vec_mul_scalar(Temp, 250.0, Temp);
		for(new i=0;i<3;i++)
			vecVelocity[i] += Temp[i]
		iCount++
	}
	// S && !W
	else if(buttons & IN_BACK && !(buttons & IN_FORWARD)) {
		angle_vector (Angles, ANGLEVECTOR_FORWARD, Temp)
		xs_vec_neg(Temp,Temp)
		xs_vec_mul_scalar(Temp, 250.0, Temp);
		for(new i=0;i<3;i++)
			vecVelocity[i] += Temp[i]
		iCount++
	}
	// D && !A
	if(buttons & IN_LEFT && !(buttons & IN_RIGHT)) {
		angle_vector (Angles, ANGLEVECTOR_RIGHT,Temp)
		xs_vec_neg(Temp,Temp)
		xs_vec_mul_scalar(Temp, 250.0, Temp);
		for(new i=0;i<3;i++)
			vecVelocity[i] += Temp[i]
		iCount++
	}
	// A && !D
	else if(buttons & IN_RIGHT && !(buttons & IN_LEFT)) {
		angle_vector (Angles, ANGLEVECTOR_RIGHT,Temp)
		xs_vec_mul_scalar(Temp, 250.0, Temp);
		for(new i=0;i<3;i++)
			vecVelocity[i] += Temp[i]
		iCount++
	}
	
	if(iCount == 0)
		return;
		
	for(new i=0;i<3;i++)
		vecVelocity[i] /= iCount
		
	//vecVelocity[2] = f_OldFallVelocity
	
	set_pev(ent,pev_velocity,vecVelocity)
}

którą odpalam gdy gracz naciska w, a, s lub d.
Byt musi mieć wymiary maksymalne, bo chcę, abu kolidował ze światem.
Ustawiam je w ten sposób

set_pev(entity[id],pev_mins, Min);
set_pev(entity[id],pev_maxs ,Max);

entity[id] to globalny identyfikator bytu, który został stworzony przez gracza.
Gdy gracz jest martwy, byt jest usuwany.
Kamera jest trzeciosobowa (próbowałem ustawić attachview'em w sam byt, ale nie wyglądało to najlepiej), jednak myśle że nie ma to większego znaczenia.
Byt to "bomba" (model c4), która sterowana przez gracza ma dojść w określone miejsce.

Kolejnym powodem dla którego byt musi mieć wymiary jest wymagana ustrzelalność..


Edited by NoLiFeR, 28.02.2016 21:15.
Quote

  • +
  • -
grankee's Photo grankee 28.02.2016

Co dokładnie się dzieje? Nie mam jak przetestować moich przypuszczeń, ale tak:

 

-Zakładam, że funkcja ta jest odpalana w prethinku

-Zmienna iCount to wielka zagadka :) jeżeli funkcja odpalana jest w prethinku tak jak zakladam to wartosc iCount może wynosić 0,1,2,3 lub 4 zależnie ile przycisków trzymasz w danej klatce.

Jaki sens ma zatem dzielenie vectora przez 1,2,3 lub 4? (przy zerze funkcja zostanie wcześniej przerwana i słusznie, bo przez 0 się nie dzieli)

for(new i=0;i<3;i++)
		vecVelocity[i] /= iCount

Zakładam, że chciałeś jej użyć do spokojnego przyspieszania, ale jest ona deklarowana na nowo za każdym wywołaniem funkcji więc nigdy nie pójdzie wyżej.

 

 

Zobacz jak to zadziała:

public poruszanie(ent, id, Float:Angles[3], buttons) {
	new Float:vecVelocity[3];
	//pev(ent, pev_velocity, vecVelocity)
//	new Float:f_OldFallVelocity = vecVelocity[2]
		
	static  iCount[32] ; 
	new iTrzymaRuch=0;
	new Float:Temp[3];
	// W && !S
	if(buttons & IN_FORWARD && !(buttons & IN_BACK)) {
		angle_vector (Angles, ANGLEVECTOR_FORWARD, Temp)
		if(iCount[id]<250)	iCount[id]++
		iTrzymaRuch=1;
	}
	// S && !W
	else if(buttons & IN_BACK && !(buttons & IN_FORWARD)) {
		angle_vector (Angles, ANGLEVECTOR_FORWARD, Temp)
		xs_vec_neg(Temp,Temp)
		if(iCount[id]<250)	iCount[id]++
		iTrzymaRuch=1;
	}
	
	// D && !A
	if(buttons & IN_LEFT && !(buttons & IN_RIGHT)) {
		angle_vector (Angles, ANGLEVECTOR_RIGHT,Temp)
		xs_vec_neg(Temp,Temp)
		if(iCount[id]<250)	iCount[id]++
		iTrzymaRuch=1;
	}
	// A && !D
	else if(buttons & IN_RIGHT && !(buttons & IN_LEFT)) {
		angle_vector (Angles, ANGLEVECTOR_RIGHT,Temp)
		if(iCount[id]<250)	iCount[id]++
		iTrzymaRuch=1;
	}
	
	if(iTrzymaRuch==0)
	{
		iCount[id]=0;
		return;
	}
		
	xs_vec_mul_scalar(Temp, float(iCount[id]), Temp);
	for(new i=0;i<3;i++)
		vecVelocity[i] += Temp[i]
	
		
	//vecVelocity[2] = f_OldFallVelocity
	
	set_pev(ent,pev_velocity,vecVelocity)
}

Edited by grankee, 29.02.2016 00:13.
Quote

  • +
  • -
Best Answer NoLiFeR's Photo NoLiFeR 29.02.2016

Jak wciskam jednocześnie W i D to prędkość będzie sumą dwóch wektorów. Dziele przez iCount tylko po to aby nie dało się poruszać klawiszami w i d szybciej niż samym w.

Problem rozwiązany, ostatni movetype okazał się zbawienny :) ( MOVETYPE_PUSHSTEP )



// Funkcja działa idealnie, a zastosowany wyżej movetype sprawia że sam byt porusza się jak na lodzie (płynne przyspieszanie)
Edited by sebul, 01.03.2016 19:50.
Quote

  • +
  • -
grankee's Photo grankee 29.02.2016

for(new i=0;i<3;i++)
		vecVelocity[i] /= iCount

nie dziel vecVelocity[2] bo ono odpowiada za prędkość w pionie, a tej niepotrzeba zmniejszać jeśli trzymasz dwa przyciski :P

Quote

  • +
  • -
NoLiFeR's Photo NoLiFeR 29.02.2016

Trafna uwaga, dostrzegłem to dodając skakanie :) Dla osób które chciały by podpatrzeć kod, zmieniłem jeszcze IN_RIGHT IN_LEFT na IN_MOVERIGHT i IN_MOVELEFT, co dało efekt końcowy (no prawie, bo zmieniłem iCount na fCount oraz dodawałem 0,5 zamiast 1, przez to dzieli teraz max przez 1.5 (wartość początkowa to 0.5). Zrobiłem tak bo byt był zbyt zatrzymywany przez to dzielenie) Zmieniłem sprawdzanie iCount == 0 na fCount == 0.5, bo taka jest wartość początkowa (skoro nic się nie zmieniło, po co co kolwiek dodawać?). Skok jest wykonywany przed tą czynnością, także gdy gracz użyje skoku a nie użyje W, A ,S czy D wartość fCount zostanie powiększona o 0.5, aby nie przerwało funkcji (i żeby nie trzeba było robić obejść).

Dziękuje wszystkim za pomoc, temat się wyczerpał więc proszę o jego zamknięcie.

Quote

  • +
  • -
sebul's Photo sebul 01.03.2016

Wiadomość wygenerowana automatycznie


Ten temat został zamknięty przez moderatora.

Powód: Pomoc udzielona

Jeśli się z tym nie zgadzasz, report.png raportuj ten post, a moderator lub administrator rozpatrzy go ponownie.


Z pozdrowieniami,
Zespół AMXX.PL
Quote
Locked